阅读本节,须要理解vue的数据驱动原理。vue
new Vue({ data: { msg: 'hello', say: 'hello world', }, watch: { msg(newVal) { this.say = newVal + ' world'; } } })
vue的data包括2个属性msg和say,watch中监听msg并更新say的值。数组
function Vue (options) { if ("development" !== 'production' && !(this instanceof Vue) ) { warn('Vue is a constructor and should be called with the `new` keyword'); } this._init(options); }
new Vue会执行原型上的_init方法, _init方法中hi调用 initState,这个方法会初始化全部状态相关内容函数
initStatus会判断若是咱们定义了watch则执行initWatch学习
function initWatch (vm, watch) { for (var key in watch) { var handler = watch[key]; if (Array.isArray(handler)) { for (var i = 0; i < handler.length; i++) { createWatcher(vm, key, handler[i]); } } else {
createWatcher(vm, key, handler); } } }
这段代码意思是若是watch声明了一个数组,则遍历数组并调用createWatcher,若是不是数组就直接调用createWatcher传递过去。这就证实,watch咱们能够声明多个处理函数。this
createWatcher主要工做是处理传入值,传入不一样的值,作不一样的兼容处理spa
function createWatcher ( vm, expOrFn, handler, options ) { // 若是handler是对象,则获取handler下面的handler属性看成watch的执行函数 if (isPlainObject(handler)) { options = handler; handler = handler.handler; } // 若是handler是字符串,则获取vue原型上的方法 if (typeof handler === 'string') { handler = vm[handler]; } // 调用vue原型上的$watch return vm.$watch(expOrFn, handler, options) }
经过以上咱们能够看出,watch定义有不少种类型,好比:prototype
new Vue({ watch: { // 字符串 test1: 'handleTest', // 对象 test2: { handler(newVal) { // .... } } }, methods: { handleTest(newVal) { // ... } } })
Vue.prototype.$watch = function ( expOrFn, cb, options ) { var vm = this; if (isPlainObject(cb)) { return createWatcher(vm, expOrFn, cb, options) } options = options || {}; options.user = true; // new 一个Watcher实例 var watcher = new Watcher(vm, expOrFn, cb, options); if (options.immediate) { cb.call(vm, watcher.value); } return function unwatchFn() { watcher.teardown(); } };
经过以上代码能够看出,watch的建立最终实际上是vue内部建立了一个Watcher实例。那么Watcher是vue中很重要的一部分,它是数据驱动不可缺乏的一部分。code
接下来大概讲一下new Watcher的功能是什么样的。server
vue在拿到了要监听的属性和属性更新执行的函数后,new Watcher建立一个Watcher。对象
Watcher是订阅者,它“监听更新行为”并执行更新函数。
为何双引号?其实不是它在监听。以最初的代码为例更新步骤以下:
1. vue内部new Watcher建立一个Watcher实例
2. Watcher实例建立时会将本身添加到data.msg的Observer中(数据驱动原理知识)
3. 当咱们改变msg值时,msg Observer会通知全部被观察者,其中就包括以上Watcher。(数据驱动原理知识)
4. Watcher触发更新而且执行回调,所以执行了咱们声明的函数。
watch的实现很简单,这里须要vue的数据驱动原理,由Object.defileProperty、Dep、Watcher几部分实现。不了解的能够先去学习这部份内容。