初始化

function initWatch (vm: Component, watch: Object) {
for (const key in watch) {
const handler = watch[key]
if (Array.isArray(handler)) {
for (let i = 0; i < handler.length; i++) {
createWatcher(vm, key, handler[i])
}
} else {
createWatcher(vm, key, handler)
}
}
}

watch 对象做遍历,拿到每一个 handlerVue 支持 watch 的同一个 key 对应多个 handler,所以如果 handler 是一个数组,则遍历这个数组,调用 createWatcher 方法,否则直接调用 createWatcher

function createWatcher (
vm: Component,
expOrFn: string | Function,
handler: any,
options?: Object
) {
if (isPlainObject(handler)) {
options = handler
handler = handler.handler
}
if (typeof handler === 'string') {
handler = vm[handler]
}
return vm.$watch(expOrFn, handler, options)
}

hanlder 的类型做判断,拿到它最终的回调函数,最后调用 vm.$watch(keyOrFn, handler, options) 函数,$watchVue 原型上的方法

Vue.prototype.$watch = function (
expOrFn,
cb,
options
) {
var vm = this;
if (isPlainObject(cb)) {
return createWatcher(vm, expOrFn, cb, options)
}
options = options || {};
options.user = true;
var watcher = new Watcher(vm, expOrFn, cb, options);
if (options.immediate) {
try {
cb.call(vm, watcher.value);
} catch (error) {
handleError(error, vm, ("callback for immediate watcher \"" + (watcher.expression) + "\""));
}
}
return function unwatchFn () {
watcher.teardown();
}
};

$watch 方法是用户可以直接调用的,它可以传递一个对象,也可以传递函数,先判断 cb 如果是一个对象,则调用 createWatcher 方法,接着执行 const watcher = new Watcher(vm, expOrFn, cb, options) 实例化了一个 watcher,如果设置了 immediate 为 true,则直接会执行回调函数 cb。最后返回了一个 unwatchFn 方法,它会调用 teardown 方法去移除这个 watcher

get () {
pushTarget(this)
let value
const vm = this.vm
try {
value = this.getter.call(vm, vm)
} catch (e) {
if (this.user) {
handleError(e, vm, `getter for watcher "${this.expression}"`)
} else {
throw e
}
} finally {
// "touch" every property so they are all tracked as
// dependencies for deep watching
if (this.deep) {
traverse(value)
}
popTarget()
this.cleanupDeps()
}
return value
}

后来看了Watcher构造函数的逻辑想了半天watch监听的属性是如何关联当前Watcher的,原来在get函数里value = this.getter.call(vm, vm)这句代码巧妙的收集了依赖,在watch初始化之前data已经初始化完毕,this.getter.call(vm, vm)对于watch的监听器来说实质上是获取当前监听的属性,在获取属性时可以收集依赖

至于watch的使用用法可以参考:Vue.js中 watch 的高级用法

源码分析参考:watch

最新文章

  1. hibernate......1、2级缓存
  2. 【转】Velocity模板(VM)语言介绍
  3. 如何在Mvc 6 中创建 Web Api以及如何脱离IIS实现自我托管
  4. 使用Grunt启动和运行
  5. LINUX&amp;UNIX 安装vmware workstation10和centOS6
  6. 61.MII、RMII、GMII接口的详细介绍
  7. 桶排序-Swift
  8. Javascript 精髓整理篇之二(函数篇)postby:http://zhutty.cnblogs.com
  9. AtCoder Beginner Contest 073
  10. 安卓高级Fresco图片框架的时候
  11. python:解析js中常见的 不带引号的key的 json
  12. bootstrap_开始
  13. [C#]关于DataDirectory的一些思考
  14. C#泛型中的抗变和协变
  15. openstack学习-创建一台云主机(七)
  16. 早期(编译器)优化--Java语法糖的味道
  17. js实现禁止pc端浏览器缩放和获取当前页面浏览器的缩放大小
  18. JAVA WEB -- request
  19. Spring集成MyBatis的使用-使用Mapper映射器
  20. RESTful URL设计指南(转)

热门文章

  1. 基于LNMP架构部署NextCloud私有云盘
  2. lwip netbuf
  3. 如何分析和研究Log文件 ,如何看日志信息
  4. 【转载】signal(SIGCHLD, SIG_IGN)和signal(SIGPIPE, SIG_IGN)
  5. WARNING: The host &#39;$hostname&#39; could not be looked up with resolveip. (转)
  6. bootstrap--网格化布局
  7. Jmeter 连接Redis获取数据集
  8. MySQL分析工具explain介绍
  9. clr via c# delegate
  10. 【原创】关于pyinstaller打包的程序执行出错问题,pyinstaller3.5只支持matplotlib3.0.2已经解决