前言
首先让我们看看初始化的watch的源码!
function Vue(){
//初始化属性,data,computed,props,watch等等
initState(this)
}
function initState(vm) {
//......
if (opts.watch) {
initWatch(this, vm.$options.watch);
}
}
function initWatch(vm, watch) {
//遍历watch,为 每一个 watch添加订阅者就是user-watcher
for (var key in watch) {
var watchOpt = watch[key];
createWatcher(vm, key, handler);
}
}
function createWatcher(
vm,
expOrFn,
handler,
options
) {
//不同的watch写法,得到的hander也是不一样的
if (isPlainObject(handler)) {
options = handler;
handler = handler.handler;
}
if (typeof handler === 'string') {
handler = vm[handler];
}
//expOrFn是key ,handler是该key的监听回调,下面会很多次说起(监听回调)
return vm.$watch(expOrFn, handler, options)
}
按步骤一步一步看下来 上面先遍历watch,后面给每个侦听属性添加一个user-watcher
,其中传的参数expOrFn
是key,handler
是该key的监听回调,handler
的取值可能会有几种情况,列出我们可能的watch形式。
watch:{
name:{
handler(){},
},
name(){},
name:"getNameWatch"
}
是一个对象时,就把该对象的handler
赋值handler
,函数的话就直接赋值handler
,字符串就把vm.getNameWatch
赋值给handler
。
好了,之后我们看看$watcher
发生了什么。
Vue.prototype.$watch = function (
expOrFn,
cb,
options
) {
//下面会说
var watcher = new Watcher(vm, expOrFn, cb, options);
//立即执行一次该侦听wather
if (options.immediate) {
cb.call(vm, watcher.value);
}
};
让我们快速吧视线移到new Watcher(),
就是给每个侦听属性添加的user-watcher
,看下Watcher
源码,我会针对该知识,列重要的源码,就不累赘别的代码了。
var Watcher = function (vm, key, cb, opt) {
this.vm = vm;
this.deep = opt.deep;
this.cb = cb;
// 下面这段主要是设置该key的监听回调
this.getter = parsePath(expOrFn);
};
// this.get 作用就是执行 this.getter()
this.value = this.get();
};
function parsePath(path) {
var segments = path.split('.');
return function (obj) {
for (var i = 0; i < segments.length; i++) {
if (!obj) {
return
}
obj = obj[segments[i]];
}
return obj
}
}
parsePath
主要返回了一个匿名函数,函数中的内容主要是会从vm
上获取该侦听key
的value
,这样会发生依赖收集。
看看之后的执行吧,之后赋值给this.getter
,之后执行this.get()
就是执行this.getter()
,执行了就会对该侦听属性进行依赖收集。说了这么多还是稍微多一个过程看吧。
我们已经知道parsePath会返回该侦听属性的监听回调。接下里继续 执行this.get()方法。
Watcher.prototype.get = function get() {
//把当前的user-watcher设置为Dep.target
pushTarget(this);
//把vm传进去,执行监听的回调,之后如果回调中有依赖的响应会触发它的依赖收集user-watcher。
value = this.getter.call(vm, vm);
var vm = this.vm;
if (this.deep) {
traverse(value);
popTarget();
}
return value
};
value = this.getter.call(vm, vm);
这段会依赖收集watcher中的 key的订阅者,此时Dep.target是 user-watcher所以会被收集到subs数组中。
之后返回this.get()
返回到this.value
,再退到上面就是Vue.prototype.$watch
中new Watcher()
返回的watcher
,再判断immediate
是否为true
表示立即执行一次该key
的handler
回调啦 。接着initWatch就大功告成了。
之后在响应数据发生变化的时候就会派发更新,执行update
就会执行user-watcher的监听回调啦啦啦!
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!