watch

watch选项的初始化也在 initState

function initState (vm) {
  if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch);
  }
}

initWatch

遍历传入的watch选项,逐个创建Watcher。 watch 的key 有几种传入方式

  1. 对象
    {
    	handle,
    	deep,
    	immediate
    }
    
  2. methods中方法名
    watch: {
    	key: "handleWatch"
    },
    methods: {
    	handleWatch(){}
    }
    
  3. 直接传入的处理函数
    watch: {
    	key:function(){}
    }
    
  4. 以上类型组合的数组
    watch: {
    	key: [ {...}, fn, "handle"]
    }
    
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);
    }
  }
}

createWatcher

处理过后的handler始终是一个函数,调用$watch为监听的属性创建一个Watcher

function createWatcher ( vm, expOrFn,handler,options) {
  // 对象类型: 取对象的handler	
  if (isPlainObject(handler)) {
    options = handler;
    handler = handler.handler;
  }
  // handler是方法名,从实例上取得方法
  if (typeof handler === 'string') {
    handler = vm[handler];
  }
  return vm.$watch(expOrFn, handler, options)
}

vm.$watch

  • expOrFn: 监听的属性名
  • cb: 上文传入的handler监听函数
    创建Watcher,过程中会读取 data 中相应的属性,从而触发属性的getter收集此Watcher
Vue.prototype.$watch = function ( expOrFn,cb,options) {
    var vm = this;
    options = options || {};
    options.user = true;
    // 读取属性,收集依赖
    var watcher = new Watcher(vm, expOrFn, cb, options);
    // 当设置了 immediate 属性,则现在就调用handler函数,而不是等数据变化时才触发
    if (options.immediate) {
      var info = "callback for immediate watcher \"" + (watcher.expression) + "\"";
      pushTarget();
      invokeWithErrorHandling(cb, vm, [watcher.value], vm, info);
      popTarget();
    }
    return function unwatchFn () {
      watcher.teardown();
    }
  };

简化版创建的Watcher

  • expOrFn: 属性的key
  • cb: handler函数
  • options: {deep?,immediate?}
function Watcher (vm,expOrFn,cb,options) {
    this.deep = options.deep
  }
  // handler函数
  this.cb = cb;
  // 传入的key或表达式
  this.getter = expOrFn;
  // 读取属性
  this.value = this.get();
};

Watcher.prototype.get = function() {
  // 将当前的 Watcher 推到全局位置,用于属性的dep收集它
  pushTarget(this);
  // 触发属性的getter并收集依赖
  var value = this.getter.call(vm, vm);
  // 如果传入了 deep 选项,则让该属性的所有嵌套属性均收集此Wather,该嵌套的任一属性发生变化都能收到更新回调
  if (this.deep) {
    traverse(value);
  }
  return value
};

监听的数据发生变化时,会将此数据收集的所有Watcher加入到更新队列中,在本轮事件循环的末尾,依次取出Watcher调用更新方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值