Hi大家好,节日快乐~咳咳,前面两篇文章我们从设计的角度讲了Vue2的响应式原理和实现,并详细分析计算属性等等。本文是本系列的最后一篇文章。下面说说listening属性和vm.$watch,再回到设计总结一下Vue2的响应式。前两篇没看过的,先看前一篇,再来,传送门:Vue2响应式原理解析(一):从设计入手,Vue2响应式原理解析(二):计算属性揭晓。Listeningpropertywatch对listening属性的使用不是很了解。相信大家都不陌生。无非是定义一个函数,当要监控的值发生变化时会被回调。下面直接来看康康的关键代码是如何实现的。打开src/core/instance/state.js文件,找到initState:道具)if(opts.methods)initMethods(vm,opts.methods)if(opts.data){initData(vm)}else{observe(vm._data={},true/*asRootData*/)}if(opts.computed)initComputed(vm,opts.computed)if(opts.watch&&opts.watch!==nativeWatch){initWatch(vm,opts.watch)//监听属性的初始化在最后。}}在这个函数中,可以看到熟悉的initData和initComputed,之前已经提过。initWatch是监听属性初始化的函数。这里注意最后调用了initWatch,传入了vm对象(其实就是监听vm上的属性),也就是说监听属性也可以监听计算属性的变化哟。initWatch的内容很简单,我们只看关键代码:)){for(leti=0;i){//...Vue.prototype.$watch=function(expOrFn:string|Function,cb:any,options?:Object):Function{constvm:Component=this//...options=选项||{}options.user=trueconstwatcher=newWatcher(vm,expOrFn,cb,options)//立即评估if(options.immediate){try{cb.call(vm,watcher.value)}catch(error){//...}}returnfunctionunwatchFn(){watcher.teardown()}}}这里我们看到vm.$watch实际上生成了一个Watcher对象。有几个地方需要健康:expOrFn,这里是需要监控的属性值。options.user,表示是用户自定义的,watcher更新时会调用用户自定义的回调函数cb。options.immediate,立即求值,会将当前值传递给一开始定义的监听函数。unwatchFn,可以手动关闭monitor(当然定义的monitor属性不需要这个)。expOrFn在这里我将重点介绍expOrFn。expOrFn可以支持属性表达式,根据Vue文档:观察Vue实例上表达式或函数计算结果的变化。也就是说可以这样设置:vm.$watch('a.b',function(newVal,oldVal){//当属性a改变或者a.b改变时触发})vm.$watch(function(){returnthis.c+this.d},function(newVal,oldVal){//当属性c改变或d改变时触发})第一种情况下,expOrFn是一个表达式。在src/core/observer/watcher.js中找到Watcher的构造函数://...if(typeofexpOrFn==='function'){this.getter=expOrFn}else{this.getter=parsePath(expOrFn)//...}//...我们知道watcher.getter需要是一个函数,parsePath在src/core/util/lang.js:exportfunctionparsePath(path:string):any{//...constsegments=path.split('.')returnfunction(obj){for(leti=0;i