Vue では、computed はフィルターに似た計算プロパティで、ビューにバインドされたデータを処理し、変更をリッスンします。複雑なデータ型を監視するには、watch で詳細な監視を使用する必要があります。どちらも vue 上のデータ変更を検出できます。 Vue とは異なり、WeChat アプレットはウォッチと計算を使用して、対応する変更を加えることができます。アプレット内の関数 this.setData() のみがデータを検出できるため、アプレット内のデータ変更を検出する必要があるたびに、この関数を手動で実行する必要があります。さらに、アプレットは、データ変更を検出するためにこれら 2 つの関数をアタッチすることもできます。
Vue は、Object.defineProperty を通じてデータ変更検出を実装します。すべてのバインディング操作を変数のセッターに挿入すると、変数が変更されたときに他のデータも変更される可能性があります。実際、小さなプログラムでの実装は vue よりも簡単です。これは、データ内のオブジェクトの場合、vue はオブジェクト内の各変数を再帰的にバインドして応答性を持たせる必要があるためです。ただし、WeChat アプレットでは、オブジェクトであろうと基本型であろうと、 this.setData() を通じてのみ変更できます。このようにして、データ内のキーではなく、データ内のキー値の変更を検出するだけで済みます。キーの値。
テスト コード:
Page({ data: { test: { a: 123 }, test1: \'test1\', }, onLoad() { computed(this, { test2: function() { returnthis.data.test.a + \'2222222\' }, test3: function() { returnthis.data.test.a + \'3333333\' } }) watch(this, { test:function(newVal) { console.log(\'invoke watch\') this.setData({test1: newVal.a + \'11111111\' }) } }) }, changeTest() { this.setData({ test:{ a: Math.random().toFixed(5) } }) }, })
次に、テストが変更されると test1、test2、test3 も変更されるように監視メソッドと計算メソッドを実装する必要があるため、ボタンが追加されています。このボタンをクリックするとテストが変更されます。
watch メソッドは比較的単純です。まず、変更を検出する関数を定義します:
function defineReactive(data, key, val, fn) { Object.defineProperty(data, key, { configurable: true, enumerable: true, get: function() { return val }, set: function(newVal){ if (newVal === val)return fn &&fn(newVal) val = newVal }, }) }
次に、watch 関数によって渡されたオブジェクトを反復処理し、キーごとにメソッドを呼び出します
function watch(ctx, obj) { Object.keys(obj).forEach(key => { defineReactive(ctx.data, key, ctx.data[key], function(value) { obj[key].call(ctx,value) }) }) }
ここでのパラメータは fn で、上記の watch メソッドの test の値です。ここで、メソッドはレイヤーにラップされ、コンテキストにバインドされています。
計算結果を見てみましょう。データ内のどの変数が計算結果に依存するのかが分からないため、これは少し複雑になります。そのため、データ内の各変数を走査することしかできません。
function computed(ctx, obj) { let keys =Object.keys(obj) let dataKeys =Object.keys(ctx.data) dataKeys.forEach(dataKey => { defineReactive(ctx.data, dataKey, ctx.data[dataKey]) }) let firstComputedObj =keys.reduce((prev, next) => { ctx.data.$target =function() { ctx.setData({[next]: obj[next].call(ctx) }) } prev[next] =obj[next].call(ctx) ctx.data.$target =null return prev }, {}) ctx.setData(firstComputedObj) }
このコードを詳しく説明すると、まずデータ内の各属性に対してdefineReactiveメソッドを呼び出します。次に、computed の各属性の最初の値 (上記の例では test2 と test3) を計算します。
computed(this, { test2: function() { returnthis.data.test.a + \'2222222\' }, test3: function() { returnthis.data.test.a + \'3333333\' } })
ここでは、test2 と test3 の値をそれぞれ呼び出し、戻り値と対応するキー値をオブジェクトに結合してから、setData() を呼び出して、これら 2 つの値が計算されるようにします。ここでは、reduce メソッドを使用します。 test2 と test3 はどちらも test に依存するため、test が変更されると、test2 と test3 の対応する関数をその setter 関数で呼び出す必要があり、これら 2 つの変数は setData を通じて設定されます。
ミニ プログラム ストアより多くのオンライン ミニ プログラムを提供
変更時に実行する必要があるすべての関数を保存する変数を宣言し、設定時に各関数を実行します。この時点では this.data.test の値は変更されていないため、setTimeout を使用して次のラウンドで再度実行します。さて、サブに機能を追加する方法について質問があります。上で述べた、reduce の 2 行のコードをまだ覚えているかどうかはわかりません。 test1 と test2 の計算値が初めて計算されるとき、test の getter メソッドが呼び出されるため、これは関数を subs に挿入し、データに $target 変数を宣言し、実行する必要のある関数を指定します。この変数を指定すると、getter 内のデータにターゲット値があるかどうかを判断できるため、subs にプッシュできます。ターゲットをすぐに null に設定する必要があることに注意してください。
Watch はこれまで実装され、計算されてきましたが、まだ終わっていません。問題があります。両方を同時に使用すると、watch のオブジェクトのキーもデータ内に存在するため、変数に対して Object.defineProperty が繰り返し呼び出され、後のもので前のものが上書きされます。 vue のように 2 つの呼び出し順序を決定できるわけではないため、computed の値を監視できるように、最初に computed を記述し、次に watch を記述することをお勧めします。
推奨事項: 「 ミニ プログラム開発チュートリアル 」
以上がアプレットは監視および計算を通じてデータをどのように検出しますかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。