一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務器之家 - 編程語言 - JavaScript - js教程 - 原生微信小程序開發中 redux 的使用詳解

原生微信小程序開發中 redux 的使用詳解

2022-01-21 15:16王唯佳 js教程

這篇文章主要介紹了原生微信小程序開發中 redux 的使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前提

復雜場景中有不少數據需要在多個不同頁面間來回使用和修改。但是小程序頁面直接的數據通信方式十分的簡單。通常情況需要自己維護一個全局的對象來存放共有數據。但是,簡單的維護一個共有數據實體,會隨著業務邏輯的不斷復雜化而變的過分龐大,并且數據的修改往往無法很好的溯源。加之公共數據實體中數據的修改和頁面的UI之間沒有太好的同步手段,往往需要在頁面和對應的數據實體中同時都維護一份相同的數據,操作十分的不方便。

之前使用過Taro以react+redux的結構來開發微信小程序,依托redux整體上可以解決上述的問題。但是Taro本身也有著一些讓人無法接受的潛在問題。本著能用原生就絕不使用第三方二次封裝的庫的原則。一直想嘗試一下在原生微信小程序開發中接入redux。

需要解決的問題

1、redux庫的接入
2、頁面UI與redux數據的綁定

redux庫的引入

1、redux的安裝,使用 npm與yarn 都可以。
具體到redux中文官網如下:https://www.reduxjs.cn/introduction/getting-started/
2、微信小程序引入外部npm包。
使用微信小程序IDEA,tools 中的 Build npm,生成miniprogram_npm。

原生微信小程序開發中 redux 的使用詳解

3、redux庫ReferenceError: process is not defined報錯的解決。

原生微信小程序開發中 redux 的使用詳解

因為微信小程序Build npm工具,構建時不會引入nodeprocess環境變量,但是redux對不同env做了對應的優化。所以導致構建出來的包缺失process變量。最便捷的解決方法是在構建完成的包中自己注入需要的process。

原生微信小程序開發中 redux 的使用詳解

這樣基本可以解決所有第三方庫遇到的process參數缺失的問題。如果每次運行Build npm工具后都需要手動修改。如果有多個第三方庫需要手動修改,那就很麻煩。所以很有必要通過腳本,使用ast樹等工具完整動態修改,節省人力成本(這個后續介紹)

綜上,redux的引入就完成了。

在項目中添加redux

1、store的創建

使用combineReducers合并不同的實體,使用createStore創建store實體,并導出。為了數據的統一性,redux的原則是一個項目只初始化一個store,所以后續任何的操作都是在當前生成的store中進行。

合并數據實體:

const { combineReducers } = require("redux");
const testItem = require("./testItem/index");
const testItem2 = require("./testItem2/index");
const user = require("./user/index");

const reducer = combineReducers({
 testItem: testItem.testItem,
 testItem2,
 user
});

module.exports = {
 reducer
}

導出store:

const { createStore, applyMiddleware } = require("redux");
const { reducer } = require("./reducers");
const { logger } = require("redux-logger");

const store = createStore(
 reducer,
 applyMiddleware(logger)
)

module.exports = {
 store
}

2、全局維護store

這里和react中的使用方法不同。微信小程序沒有對應的控件來全局維護store,所以我的做法是直接在,app.js的globalData中維護,這樣每個頁面都可以直接獲取到store
app.js:

const { store } = require("./redux/index");

//app.js
App({
 globalData: {
  $store: store,
  getState: ()=> store.getState(),
 }
})

模擬connect方法

在react中,connect方法是通過高階組件的方式實現的,但是這個方法并不適用微信小程序。好在redux有提供subscribe方法來監聽store中數據的變化。所以初步設計:
1、每當頁面計入或顯示的時候,添加監聽,頁面隱藏或銷毀時銷毀監聽
2、添加完監聽后,模擬 mapState 方法,把對應 redux 中的數據注入到頁面的data中
3、當監聽到redux中數據變化時,更新頁面data,從而實現頁面UI刷新
4、模擬mapDispatch方法,為頁面提供修改store數據的方法

pageW.js:

const { store } = require("../redux/index");

const initPage = (params = {}, connect = []) => {
 const { 
  onLoad = ()=>{},
  onShow = ()=>{},
  onHide = ()=>{},
  onUnload = ()=>{},
  data = {}
  } = params;

 const newPage = {
  ...params,
  // ----------------
  OnLoad(...p) {
   onLoad.bind(this)(...p);
  },
  OnShow(...p) {
   onShow.bind(this)(...p);
  },
  OnHide(...p) {
   onHide.bind(this)(...p);
  },
  OnUnload(...p) {
   onUnload.bind(this)(...p);
  },
  // ----------------
  // 清空監聽
  clearStoreSubscribe() {
   if (this.storeSubscribe) {
    this.storeSubscribe();
    this.storeSubscribe = undefined;
   }
  },
  // 獲取redux 中 data
  getNewData() {
   const newItems = {};

   const state = this.$store.getState();

   if (connect) {
    if ( Array.isArray(connect) ) {
     connect.forEach((key) => {
      const value = state[key];
      if (value && this.data[key] !== value) {
       newItems[key] = value
      }
     })
    } else if (typeof connect === "function") {
     const list = connect(state) || {};
     Object.keys(list).forEach((key) => {
      const value = list[key];
      if (value && this.data[key] !== value) {
       newItems[key] = value
      }
     })
    }
   }

   return newItems;
  },
  // 監聽 redux 變化
  handleReduxChange() {
   this.setData({
    ...this.getNewData(),
   });
  },
  // ----------------
  data: {
   ...data
  },
  onLoad(...p) {
   const app = getApp()
   this.$store = app.globalData.$store;
   this.setData({
    ...this.getNewData(),
   });

   this.OnLoad(...p);

   this._isOnLoad = true;
  },
  onShow (...p) {
   if (!this.storeSubscribe) {
    this.storeSubscribe = this.$store.subscribe(()=>this.handleReduxChange());
   }

   if (!this._isOnLoad) {
    this.setData({
     ...this.getNewData(),
    });
   }


   this.OnShow(...p);

   this._isOnLoad = false;
  },
  onHide(...p) {
   this.OnHide(...p);

   this.clearStoreSubscribe();
  },
  onUnload(...p) {
   this.OnUnload(...p);

   this.clearStoreSubscribe();
  },
  // ----------------
  dispatch(...p) {
   if (this.$store) {
    return this.$store.dispatch(...p);
   }
  }
 }

 return newPage;
}

const PageW = (params = {}, mapState = [], mapDispatch = ()=>{}) => {
 const page = initPage({...params}, mapState);
 const dispatchList = mapDispatch(store) || {};

 page.mapDispatch = {
  ...dispatchList
 };

 return Page(page);
}

module.exports = PageW;

PageW 中主要考慮和不足 如下問題:
1、為了保持微信小程序原有生命周名稱不變,所以事先劫持了傳入頁面的生命周期,然后用bind重新在對應生命周期完成后觸發。
2、因為redux更新數據,都會生成一個新的數據對象,所以每當監聽到數據變化,新數據和老數據會進行對比,每次setData,只放入確實發生變化的數據
3、頁面中的data,既維護了默認頁面創建的data數據,又加入了redux connect 后的數據,但是目前沒有對這個兩個數據的命名進行安全的區分,所以頁面原生data中的數據名稱必須與 connect 注入的數據不同。

測試頁面:

導入了testItem, testItem2兩個數據,導入了add2一個方法

const PageW = require("../../pageW/index");
const { ActionsFun } = require("../../redux/testItem/actions");

const page = {
 data: {
  wwj: 4
 },
 onLoad() {
  console.log("sub onLoad");
 },
 onShow() {

 },
 toTest() {
  console.log("toTest");
  wx.navigateTo({
   url: "/pages/test/index"
  })
 },
 button1() {
  console.log("button1");
  this.mapDispatch.add2();
 },
 button2() {
  const { wwj } = this.data;
  this.setData({
   wwj: wwj + 2
  });
 },
}

const mapState = [ "testItem", "testItem2" ];

const mapDispatch = ({dispatch}) => {
 return {
  add2: (params) => dispatch(ActionsFun.add(params))
 }
}

PageW(page, mapState, mapDispatch);

到此這篇關于原生微信小程序開發中 redux 的使用詳解的文章就介紹到這了,更多相關小程序 redux使用內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家! 

原文鏈接:https://juejin.cn/post/6929862191806054407

延伸 · 閱讀

精彩推薦
  • js教程用Javascript實現發送短信驗證碼間隔功能

    用Javascript實現發送短信驗證碼間隔功能

    這篇文章主要介紹了用Javascript實現發送短信驗證碼間隔功能,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以...

    愛前端的茂茂9292022-01-19
  • js教程js制作提示框插件

    js制作提示框插件

    這篇文章主要介紹了js制作提示框插件的方法,幫助大家更好的理解和使用js,感興趣的朋友可以了解下...

    lanshanxiao10212021-12-18
  • js教程Javascript的15種數組去重方法,總有一種適合你

    Javascript的15種數組去重方法,總有一種適合你

    數組去重,一般都是在面試的時候才會碰到,一般是要求手寫數組去重方法的代碼。如果是被提問到,數組去重的方法有哪些?你能答出其中的10種,面試...

    前端微視界9032021-12-31
  • js教程JS實現頁面側邊欄效果探究

    JS實現頁面側邊欄效果探究

    這篇文章主要介紹了JS實現頁面側邊欄效果探究,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以...

    行舟客4932021-12-29
  • js教程淺析JavaScript中的事件委托機制跟深淺拷貝

    淺析JavaScript中的事件委托機制跟深淺拷貝

    這篇文章主要介紹了JavaScript中的事件委托機制跟深淺拷貝,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要...

    打游戲也要有夢想5702022-01-05
  • js教程詳解JavaScript中的this指向問題

    詳解JavaScript中的this指向問題

    這篇文章主要介紹了詳解JavaScript中的this指向問題,幫助大家更好的理解和使用JavaScript,感興趣的朋友可以了解下...

    清蒸胖頭魚8502022-01-17
  • js教程Javascript實現關閉廣告效果

    Javascript實現關閉廣告效果

    這篇文章主要為大家詳細介紹了Javascript實現關閉廣告效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    愛前端的茂茂4622022-01-11
  • js教程JS實現簡單抖動效果

    JS實現簡單抖動效果

    這篇文章給大家結束了通過js實現抖動效果,非常不錯,具有參考借鑒價值,感興趣的朋友參考下吧...

    catEatBird9152022-01-12
主站蜘蛛池模板: 亚洲好骚综合 | 精品久久久久中文字幕日本 | 五月天精品视频在线观看 | 亚洲成av人片在线观看天堂无码 | 色综合伊人色综合网亚洲欧洲 | 亚洲va久久久久综合 | 爽好大快深点一视频 | 美女靠逼动漫 | 日本人做受全过程视频 | 91精品国产91热久久久久福利 | 91爱啪| 欧美综合精品一区二区三区 | 小草高清视频免费直播 | 免费看隐私美女 | 女主被男主为催奶药h | 第一福利在线导航 | 青春学堂在线观看 | 日韩欧美中文字幕出 | 欧美一级视频免费观看 | 97久久精品午夜一区二区 | 成人综合网址 | 免费网址在线观看入口推荐 | 欧美大片一区二区三区 | 国产老肥熟xxxx | 我的妹妹最近有点怪免费播放 | 国产国语videosex另类 | 久久人妻少妇嫩草AV无码 | 欧美一级级a在线观看 | 99热国产这里只有精品99 | 久久国产精品高清一区二区三区 | 亚洲色图第四色 | 我把校花黑色蕾丝胸罩脱了 | 色欧美亚洲 | 国产精品亚洲专区在线播放 | 日韩一级片免费观看 | 天天翘| 国产精品毛片久久久久久久 | 色婷婷综合久久久 | 国产精品久久国产精品99 gif | 男gay男gay男gay野外 | 国内9lporm自拍视频区 |