Home  >  Article  >  WeChat Applet  >  How does the applet detect data through watch and computed

How does the applet detect data through watch and computed

青灯夜游
青灯夜游forward
2020-04-27 09:30:312752browse

How does the applet detect data through watch and computed

In Vue, computed is a computed property, similar to a filter, that processes data bound to the view and listens for changes. To monitor complex data types, watch needs to use deep monitoring. Both of these can detect data changes on vue. Unlike Vue, the WeChat applet can use watch and computed to make corresponding changes. Only the function this.setData() in the applet can detect data, so every time the data changes in the applet needs to be detected, the function must be manually executed. In addition, the applet can also attach these two functions to detect data changes.

Vue implements data change detection through Object.defineProperty. Injecting all binding operations into the setter of the variable can drive changes in other data when the variable changes. In fact, the implementation in a small program is simpler than in vue, because for the object in data, vue needs to recursively bind each variable in the object to make it responsive. But in the WeChat applet, whether it is an object or a basic type, it can only be changed through this.setData(). In this way, we only need to detect changes in the key value in the data instead of the key in the key value.

Test code:

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) } })
},
})

Now we have to implement the watch and computed methods so that when test changes, test1, test2, and test3 also change. For this reason, a button is added. When this button is clicked , test will change.

The watch method is relatively simple. First, we define a function to detect changes:

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
},
})
}

Then iterate over the object passed in by the watch function and call the method for each key

function watch(ctx, obj) {
Object.keys(obj).forEach(key => {
defineReactive(ctx.data, key, ctx.data[key], function(value) {
obj[key].call(ctx,value)
})
})
}

The parameter here is fn, which is the value of test in the watch method above. Here, the method is wrapped in a layer and bound to context.

Let’s look at computed. This is a little more complicated because we can’t know which variable in data depends on computed, so we can only traverse each variable in data.

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)
}

Explain this code in detail. First call the defineReactive method for each attribute in data. Then calculate the first value of each attribute in computed, which is test2 and test3 in the above example.

computed(this, {
test2: function() {
returnthis.data.test.a + \'2222222\'
},
test3: function() {
returnthis.data.test.a + \'3333333\'
}
})

Here we call the values ​​of test2 and test3 respectively, combine the return value and the corresponding key value into an object, and then call setData(), so that these two values ​​will be calculated for the first time. Here we use The reduce method. Both test2 and test3 depend on test, so when test changes, the corresponding functions in test2 and test3 must be called in its setter function, and these two variables are set through setData.

Mini program storeProvide more online mini programs

Declare a variable to save all the functions that need to be executed when changing, and execute each function when set. Because the value of this.data.test has not changed at this time, use setTimeout to execute again in the next round. Now there is a question, how to add functions to subs. I don’t know if you still remember the two lines of code in reduce we mentioned above. Because when the calculated values ​​of test1 and test2 are calculated for the first time, the getter method of test will be called. This is a good opportunity to inject the function into subs, declare a $target variable on data, and assign the function that needs to be executed. Give this variable, so that you can judge whether there is a target value on data in the getter, so you can push into subs. It should be noted that you need to set the target to null immediately.

Watch has been implemented so far and computed, but it’s not over yet, there’s a problem. When using both at the same time, the key of the object in watch also exists in data, so Object.defineProperty will be called repeatedly on the variable, and the later will overwrite the previous one. Because it is not like vue where the order of calling the two can be determined, we recommend writing computed first and then watch, so that the value in computed can be watched.

Recommendation: " Mini Program Development Tutorial"

The above is the detailed content of How does the applet detect data through watch and computed. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:csdn.net. If there is any infringement, please contact admin@php.cn delete