在微信小程序里使用watch和computed的方法(2)

到此为止已经实现了 watch 和 computed,但是还没完,有个问题。当同时使用这两者的时候,watch 里的对象的键也同时存在于 data 中,这样就会重复在该变量上调用 Object.defineProperty ,后面会覆盖前面。因为这里不像 vue 里可以决定两者的调用顺序,因此我们推荐先写 computed 再写 watch,这样可以 watch computed 里的值。这样就有一个问题,computed 会因覆盖而无效。

思考一下为什么?

很明显,这时因为之前的 subs 被重新声明为空数组了。这时,我们想一个简单的方法就是把之前 computed 里的 subs 存在一个地方,下一次调用 defineReactive 的时候看对应的 key 是否已经有了 subs,这样就可以解决问题。修改一下代码。

function defineReactive(data, key, val, fn) { let subs = data['$' + key] || [] // 新增 Object.defineProperty(data, key, { configurable: true, enumerable: true, get: function() { if (data.$target) { subs.push(data.$target) data['$' + key] = subs // 新增 } return val }, set: function(newVal) { if (newVal === val) return fn && fn(newVal) if (subs.length) { // 用 setTimeout 因为此时 this.data 还没更新 setTimeout(() => { subs.forEach(sub => sub()) }, 0) } val = newVal }, }) }

这样,我们就一步一步的实现了所需的功能。完整的代码和例子请戳

虽然经过了一些测试,但不保证没有其它未知错误,欢迎提出问题。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/9e56ce7f88ccbcb196e67c7935d38801.html