watch主要用来监听组件中某个值的改变,并执行对应的回调函数。
wtach和computed的区别
- watch是一个值影响多个值
- computed是多个值影响一个值
watch的内部原理
先看源码中对于vm.$watch的实现
// watch可以监听一个表达式(a.b.c)或者函数
Vue.prototype.$watch = function (expOrFn, cb, options) {
const vm = this;
options = options || {
};
const watcher = new Watcher(vm, expOrFn, cb, options);
// 如果immediate为true,就需要立即执行一次cb
if(options.immediate) {
cb.call(vm, watcher.value);
}
// 返回一个取消监听的函数
return function unWatchFn () {
watcher.teardown();
}
}
expOrFn表示watch可以监听字符串或者函数
- 字符串(a.b.c):则会去读取vm.a.b.c,一旦值发生改变,就执行cb。
- 函数:函数中使用的所有响应式数据都会被watch监听,一旦其中某个发生改变,watcher都会得到通知。
this.$watch(function () {
return this.name + this.age;
}, function(newVal, oldVal) {
console.log(newVal, oldVal);
})
返回一个unWatchFn是为了在组件卸载时取消watch,防止内存泄漏。但是当watch写在组件内部时,可以不手动去执行unWatchFn函数,在组件卸载时会自动执行。
原理
以上面的代码为例,watch监听了name和age的变化,即watcher内部会收集name和age对应的Dep(Dep中记录了哪些watcher访问了该变量),同时Dep也会收集该watcher,这导致age和name中任意一个发生改变,watcher都会收到通知。而当我们在watcher中记录了自己订阅了哪些Dep之后,可以在teardown中通知这些Dep,让他们把wather从当前列表删除。