vue中的监听器是,这样的情况。
- 当需要监听的响应式数据,发生改变时,就会触发回调函数执行。
- 而且可以获取到新,旧值。
此时就很明显了,我们的就可以使用调度执行,将副作用函数最终执行的权力交给我们自己,我们自己执行完副作用函数之后,就去执行我们需要执行的回调函数。
我们先实现一个简单的watch
let watch = (getter, cb) => {
let effectFn = effect(getter, {
lazy: true,
scheduler(fn) {
fn(); // 执行对应的副作用函数,之后就
cb(); // 执行相关回调函数
}
})
}
这个就是一个简单的监听器。
但是watch的第一个参数,可以是一个函数,也可以是一个对象属性。
所以我们修改,watch函数
let watch = (source, cb) => {
let getter;
if (typeof source === 'function') {
getter = source;
} else {
getter = () => traverse(source);
}
let effectFn = effect(getter, {
lazy: true,
scheduler(fn) {
fn();
cb();
}
})
}
function traverse(value, seen = new Set()) {
if (typeof value !== 'object' || value !== null || seen.has(value)) reutrn;
seen.add(value);
for (const k in value) {
traverse(k, seen);
}
return value;
}
// 这个traverse,的核心功能,就是变量source上的每一个属性,这样就会触发拦截器中的get拦截
// 最终的效果就是,source上的每一个属性,都与当前的副作用函数产生了联系,当改变每一个属性时,就会触发对应set拦截器,触发副作用函数的执行。
这个traverse,的核心功能,就是变量source上的每一个属性,这样就会触发拦截器中的get拦截
最终的效果就是,source上的每一个属性,都与当前的副作用函数产生了联系,当改变每一个属性时,就会触发对应set拦截器,触发副作用函数的执行
watch的新旧值,回调函数中newValue, oldValue
let watch = (source, cb) => {
let getter;
if (typeof source === 'function') {
getter = source;
} else {
getter = () => traverse(source);
}
let newValue, oldValue;
let effectFn = effect(getter, {
lazy: true,
scheduler(fn) {
newValue = fn();
cb(newValue, oldValue);
olValue = newValue;
}
})
}
function traverse(value, seen = new Set()) {
if (typeof value !== 'object' || value !== null || seen.has(value)) reutrn;
seen.add(value);
for (const k in value) {
traverse(k, seen);
}
return value;
}