React和Vue中监听变量变化的方法

2020-06-14 06:31:45易采站长站整理

*/
export function defineReactive (
obj: Object,
key: string,
val: any,
customSetter?: ?Function,
shallow?: boolean
) {
// dep当中存放的是watcher数组
const dep = new Dep()
const property = Object.getOwnPropertyDescriptor(obj, key)
if (property && property.configurable === false) {
return
}
// cater for pre-defined getter/setters
const getter = property && property.get
const setter = property && property.set
if ((!getter || setter) && arguments.length === 2) {
// 如果第三个值没有传。那么val就直接从obj中根据key的值获取
val = obj[key] }
let childOb = !shallow && observe(val)
Object.defineProperty(obj, key, {
enumerable: true,
// 可设置值
configurable: true,
get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val
if (Dep.target) {
// dep中生成个watcher
dep.depend()
if (childOb) {
childOb.dep.depend()
if (Array.isArray(value)) {
dependArray(value)
}
}
}
return value
},
// 重点看set方法
set: function reactiveSetter (newVal) {
// 获取变量原始值
const value = getter ? getter.call(obj) : val
/* eslint-disable no-self-compare */
// 进行重复值比较 如果相等直接return
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
/* eslint-enable no-self-compare */
if (process.env.NODE_ENV !== 'production' && customSetter) {
// dev环境可以直接自定义set
customSetter()
}
// 将新的值赋值
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
childOb = !shallow && observe(newVal)
// 触发watch事件
// dep当中是一个wacher的数组
// notify会执行wacher数组的update方法,update方法触发最终的watcher的run方法,触发watch回调
dep.notify()
}
})
}

小程序

自定义Watch

小程序的data本身是不支持watch的,但是我们可以自行添加,我们参照 Vue 的写法自己写一个。

watcher.js


export function defineReactive (obj, key, callbackObj, val) {
const property = Object.getOwnPropertyDescriptor(obj, key);
console.log(property);
const getter = property && property.get;
const setter = property && property.set;
val = obj[key] const callback = callbackObj[key];
Object.defineProperty(obj, key, {
enumerable: true,
get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val
return value
},
set: (newVal) => {
console.log('start set');
const value = getter ? getter.call(obj) : val