Watch的内部原理(deep+immediate)

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从当前列表删除。

猜你喜欢

转载自blog.csdn.net/weixin_42937036/article/details/108615108