ネイティブWeChatアプレット開発におけるreduxの使用の詳細な説明

ネイティブWeChatアプレット開発におけるreduxの使用の詳細な説明

前提

複雑なシナリオでは、複数の異なるページ間で大量のデータを使用したり変更したりする必要があります。しかし、ミニプログラムページの直接データ通信方法は非常にシンプルです。通常、共通データを保存するにはグローバル オブジェクトを維持する必要があります。ただし、ビジネス ロジックが複雑になるにつれて、共有データ エンティティを単純に維持するだけでは規模が大きくなりすぎ、データの変更を適切に追跡できなくなることがよくあります。さらに、パブリック データ エンティティのデータの変更とページの UI の間には適切な同期方法がありません。ページと対応するデータ エンティティの両方で同じデータを維持する必要があることが多く、非常に不便です。

Taroは、これまでreact+reduxの構造を持つWeChatアプレットの開発に使用されていました。reduxに頼ることで、上記の問題を全体的に解決できます。しかし、太郎自体にも、受け入れがたい潜在的な問題がいくつかあります。ネイティブのライブラリを使用できる場合は、サードパーティの再パッケージ化されたライブラリを決して使用しないという原則に従います。私はずっと、ネイティブ WeChat アプレットの開発に redux を統合したいと思っていました。

解決すべき問題

1. reduxライブラリへのアクセス
2. ページUIとreduxデータのバインディング

reduxライブラリの紹介

1. redux をインストールするには、npm または yarn を使用できます。
具体的なreduxの中国公式ウェブサイトは次のとおりです:https://www.reduxjs.cn/introduction/getting-started/
2. WeChat アプレットは外部 npm パッケージを導入します。
WeChat Mini Program IDEA を使用し、ツールで npm をビルドして、miniprogram_npm を生成します。

3. エラー ReferenceError の解決方法: プロセスが redux ライブラリで定義されていません。

WeChat アプレットは npm ツールで構築されるため、構築中に nodeprocess 環境変数は導入されませんが、redux はさまざまな環境に対応する最適化を行っています。その結果、ビルドされたパッケージにはプロセス変数が不足しています。最も便利な解決策は、ビルドされたパッケージに必要なプロセスを自分で挿入することです。

これにより、基本的に、すべてのサードパーティ ライブラリで発生するプロセス パラメータの欠落の問題を解決できます。 Build npm ツールを実行するたびに手動で変更する必要がある場合。手動で変更する必要があるサードパーティライブラリが複数ある場合は面倒です。そのため、動的な変更を完了し、人件費を節約するためには、スクリプトやASTツリーなどのツールを使用する必要があります(これについては後で紹介します)

まとめると、redux の導入は完了です。

プロジェクトにreduxを追加する

1. ストアの作成

異なるエンティティをマージするには combineReducers を使用し、ストア エンティティを作成するには createStore を使用し、エクスポートします。データの統一性を保つために、Redux の原則では、プロジェクトは 1 つのストアのみを初期化し、後続の操作は現在生成されているストアで実行されます。

データ エンティティをマージします。

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

定数リデューサー = 結合リデューサー({
 テスト項目: テスト項目.テスト項目、
 テスト項目2、
 ユーザー
});

モジュール.エクスポート = {
 減速機
}

ストアをエクスポートします:

const { createStore、applyMiddleware } = require('redux');
const { リデューサー } = require('./reducers');
const { logger } = require('redux-logger');

const ストア = createStore(
 減速機、
 ミドルウェアを適用(ロガー)
)

モジュール.エクスポート = {
 店
}

2. グローバルメンテナンスストア

ここでの使用法は react の場合とは異なります。 WeChatアプレットにはストアをグローバルに維持するための対応するコントロールがないため、私のアプローチはapp.jsのglobalDataで直接維持し、各ページが直接ストアを取得できるようにすることです。
アプリ.js:

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

//アプリ.js
アプリ({
 グローバルデータ: {
  $store: ストア、
  getState: ()=> store.getState(),
 }
})

接続方法をシミュレートする

Reactでは、connectメソッドは高階コンポーネントを通じて実装されますが、このメソッドはWeChatアプレットには適用できません。幸いなことに、redux はストア内のデータの変更を監視するための subscribe メソッドを提供します。最初の設計は次のようになります。
1. ページに入るか表示されるたびにリスナーを追加し、ページが非表示または破棄されたときにリスナーを破棄します。
2. リスナーを追加した後、mapStateメソッドをシミュレートし、対応するデータをreduxでページのデータに挿入します。
3. reduxでデータの変更を監視するときは、ページデータを更新してページUIを更新する
4. mapDispatchメソッドをシミュレートして、ページがストアデータを変更するメソッドを提供します。

ページW.js:

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

const initPage = (params = {}, connect = []) => {
 定数{ 
  onLoad = ()=>{},
  onShow = ()=>{},
  非表示 = ()=>{},
  onUnload = ()=>{},
  データ = {}
  } = パラメータ;

 定数newPage = {
  ...パラメータ、
  //----------------
  OnLoad(...p) {
   onLoad.bind(this)(...p);
  },
  OnShow(...p) {
   onShow.bind(this)(...p);
  },
  OnHide(...p) {
   onHide.bind(this)(...p);
  },
  アンロード時(...p) {
   onUnload.bind(this)(...p);
  },
  //----------------
  // リスナーをクリアする clearStoreSubscribe() {
   (this.storeSubscribe)の場合{
    this.storeSubscribe();
    this.storeSubscribe = 未定義;
   }
  },
  // reduxでデータを取得する
  新しいデータを取得する() {
   定数 newItems = {};

   定数状態 = this.$store.getState();

   (接続) の場合
    Array.isArray(connect) の場合 {
     connect.forEach((キー) => {
      定数値 = 状態[キー];
      if (値 && this.data[キー] !== 値) {
       newItems[キー] = 値
      }
     })
    } そうでない場合 (typeof connect === 'function') {
     const リスト = connect(状態) || {};
     Object.keys(リスト).forEach((キー) => {
      const 値 = リスト[キー];
      if (値 && this.data[キー] !== 値) {
       newItems[キー] = 値
      }
     })
    }
   }

   新しいアイテムを返します。
  },
  // Reduxの変更をリッスンする handleReduxChange() {
   this.setData({
    ...this.getNewData()、
   });
  },
  //----------------
  データ: {
   ...データ
  },
  onLoad(...p) {
   const アプリ = getApp()
   this.$store = app.globalData.$store;
   this.setData({
    ...this.getNewData()、
   });

   this.OnLoad(...p);

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

   (!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();
  },
  //----------------
  ディスパッチ(...p) {
   もし(this.$store){
    this.$store.dispatch(...p) を返します。
   }
  }
 }

 新しいページを返します。
}

const PageW = (params = {}, mapState = [], mapDispatch = ()=>{}) => {
 const ページ = initPage({...params}, mapState);
 ディスパッチリストをマップストアに格納します。

 page.mapDispatch = {
  ...ディスパッチリスト
 };

 Page(ページ)を返します。
}

モジュールをエクスポートします。

PageW の主な考慮事項と欠陥は次のとおりです。
1. WeChat アプレットの元のライフサイクル名を変更しないために、受信ページのライフサイクルを事前にハイジャックし、対応するライフサイクルが完了した後にバインドを使用して再度トリガーします。
2. redux はデータを更新するため、新しいデータ オブジェクトが生成されます。そのため、データの変更が検出されるたびに、新しいデータと古いデータが比較されます。setData が呼び出されるたびに、実際に変更されたデータのみが挿入されます。
3. ページ内のデータは、デフォルト ページによって作成されたデータを維持するだけでなく、redux connect 後のデータも追加します。ただし、現在、これら 2 つのデータの名前を安全に区別する方法がないため、ページのネイティブ データ内のデータ名は、connect によって挿入されたデータとは異なる必要があります。

テストページ:

2つのデータ項目testItemとtestItem2をインポートし、add2というメソッドをインポートしました。

PageW は '../../pageW/index' を必要とします。
const { ActionsFun } = require('../../redux/testItem/actions');

定数ページ = {
 データ: {
  4 : 4月
 },
 オンロード() {
  console.log('sub onLoad');
 },
 オンショー() {

 },
 トテスト() {
  コンソールにログ出力します。
  wx.navigateTo({
   URL: '/pages/test/index'
  })
 },
 ボタン1() {
  コンソールにログ出力します。
  this.mapDispatch.add2();
 },
 ボタン2() {
  定数 wwj は this.data です。
  this.setData({
   wwj: wwj + 2
  });
 },
}

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

const mapDispatch = ({dispatch}) => {
 戻る {
  add2: (params) => ディスパッチ(ActionsFun.add(params))
 }
}

PageW(ページ、マップ状態、マップディスパッチ);

ネイティブ WeChat アプレットの開発における redux の詳細な使用に関するこの記事はこれで終わりです。アプレットでの redux の使用に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。皆様が今後も 123WORDPRESS.COM を応援してくれることを願っています。

以下もご興味があるかもしれません:
  • ミニプログラムに redux/immutable/thunk サードパーティライブラリを統合する方法
  • WeChatアプレットReduxバインディング例の詳細な説明

<<:  Ubuntu 16.04 にソースコードから Mininet をインストールする

>>:  WindowsでMysql5.7.17のインストールと起動に失敗する問題を解決する

推薦する

MySQL における 10 進数型の使用法の簡単な紹介

MySQL でサポートされている浮動小数点型は、 FLOAT 、 DOUBLE 、およびDECIMA...

Dockerコンテナの入退出方法の詳細な説明

1 Dockerサービスを開始するまず、docker サービスを開始する方法を知っておく必要がありま...

Vue3の組み込みコンポーネントであるTeleportの使い方を詳しく説明します

目次1. テレポートの使用2. モーダルダイアログコンポーネントを完成させる3. コンポーネントのレ...

Linux で AutoFs マウント サービスをインストールするチュートリアル

Samba サービスでも NFS サービスでも、サーバーの起動時にリモート共有リソースが自動的にマ...

制限およびオフセット ページング シナリオを使用すると速度が遅くなるのはなぜですか?

質問から始めましょう5 年前、私が Tencent にいたとき、ページング シナリオでは MySQL...

Linux で Multitail コマンドを使用するチュートリアル

MultiTail は、tail コマンド機能と同様に、複数のドキュメントを同時に監視するために使用...

Vue でルーティング遷移効果を実装する 4 つの方法

Vue ルーター トランジションは、Vue プログラムにパーソナライズされたエフェクトをすばやく簡単...

mysql5.7 でユーザーの初期パスワードを変更する方法

ユーザーが初めて MySQL データベースをインストールするとき、初期のルート パスワードを変更する...

Vueのカスタムイベントコンテンツ配信の詳細な説明

1. これは理解するのが少し複雑なので、原理を注意深く読んで自分で入力していただければ幸いです。 &...

HTMLは角丸四角形を簡単に実装します

質問: div+css と配置を使用して角丸四角形を実現するにはどうすればよいですか?ソリューション...

JavaScript に関する 6 つの奇妙で便利な点

目次1. 解体のヒント2. デジタルセパレーター3. try...catch...finally が...

Linux でユーザーをグループに追加する 4 つの方法の概要

序文Linux グループは、Linux でユーザー アカウントを管理するために使用される組織単位です...

CSSはボックスコンテナ(div)の高さを常に100%に設定します。

序文ブラウザをどのようにズームしても、ボックス コンテナーの高さを常に 100% に保つ必要がある場...

CentOS8でルートパスワードを素早く変更する方法

Centos8仮想マシンを起動し、上下キーを押して図1のインターフェースの最初の行を選択します。図1...