watch和computed是姊妹篇,前言同上。

为啥姊妹呢,因为computed初始化完了就是初始化watch:

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:

function createWatcher (
vm,
expOrFn,
handler,
options
) {
if (isPlainObject(handler)) {
options = handler;
handler = handler.handler;
}
if (typeof handler === 'string') {
handler = vm[handler];
}
return vm.$watch(expOrFn, handler, options)
}

从上面的代码可以看出初始化的时候定义在watch上的那些key-value和调用实例的$watch走的是一回事。所以还是看看$watch:

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***mediate) {
try {
cb.call(vm, watcher.value);
} catch (error) {
handleError(error, vm, ("callback for immediate watcher \"" + (watcher.expression) + "\""));
}
}
return function unwatchFn () {
watcher.teardown();
}
};
}

看到没,又是watcher,这里的options是undefined,但是要注意到,options.user = true; 这个很重要是因为刷新任务队列的时候watch里的watcher的cb回调函数就是根据这个参数去调用的。我在写到这里的时候其实想吐槽一句vue就是vue框架的的整个机制大到vuex,vue-router小到这种数据的相应式绑定都跟watcher有关,不过我第一次发现这个的时候倒是觉着挺妙的,其他的倒也没啥。

(n年后的补充:一个工具在一个框架内部要去实现响应式更新,无论路由也好,状态管理也好,其,要实现更新,更定是要利用框架现有的机制的,vue的watcher,react的setstate等等,不然能咋办呢)

这个函数里需要注意到一个地方就是实例化watcher的时候,是吧当前watch的key传进去了,此时,expOrFn是一个字符串类型,这个时候,Watcher构造函数的执行是这样的:

this.getter = parsePath(expOrFn);

parsePath长这样:

function parsePath (path) {
if (bailRE.test(path)) {
return
}
var segments = path.split('.');
return function (obj) {
for (var i = 0; i < segments.length; i++) {
if (!obj) { return }
obj = obj[segments[i]];
}
return obj
}
}

返回的闭包函数就是当前watcher的getter,闭包了当前的'key',这个key也可以是‘key.key.key’,这个有啥用放到后边说,watcher走到最后一步的时候会调用watcher实例的get进行依赖收集,然后依赖收集的时候有这么一句:

value = this.getter.call(vm, vm);

所以再回到上边那个闭包函数中,此时调用的时候obj参数就引用了当前的vm,而下边的for循环则是一步步具体化watch要watch的路径,触发这条路径上所有的get,进行依赖收集,比方说我们watch了一个'key.key',那么vm['key'],vm['key']['key']会依次调用,此时watch里key值派生的watcher也被依赖收集机制 收集了进去。然后一个watch就这么初始化完毕啦。

随机推荐

  1. 常用的git提交代码命令

    日常开发使用的git提交代码的方法 一.初始化本地仓库,提交代码,提交到远程git仓库 1.初始化代码仓库git init2.将当前目录下的所有文件放到暂存区git add .3.查看文件状态git ...

  2. lg8936题解

    虽然这道题的题目标签有颜色段均摊和并查集,但是这道题的做法与这两个算法并无关系. 考虑从询问的右往左扫描数组.设\(g_i\)表示以第\(i\)个询问为左端点,最大的\(g_i\)令\(sol(1,n ...

  3. Centos7 MyCat2 安装部署

    部署MyCat2 之前需要搭建好数据库的主从,详看文档:mysql 主次数据库搭建 官网:http://www.mycat.org.cn/ 官方文档: https://www.yuque.com/cc ...

  4. Mysql数据库基础第五章:(二)视图

    Mysql数据库基础系列 软件下载地址 提取码:7v7u 数据下载地址 提取码:e6p9 mysql数据库基础第一章:(一)数据库基本概念 mysql数据库基础第一章:(二)mysql环境搭建 mys ...

  5. codeforce D. Concatenated Multiples

    http://codeforces.com/contest/1029/problem/D 看C题的第一眼就觉得自己一定能做出来,结果就兴致勃勃地做了一天,最后做出来了.但看到这道题时,第一感觉就是&q ...

  6. UE打LOG整理

    Kismet库 蓝图方法cpp使用 例:打LOG:Print String 蓝图节点的鼠标tips:Target is Kismet System Library #include "Run ...

  7. C语言中static关键字用法

    概述 static关键字在c语言中比较常用,使用恰当能够大大提高程序的模块化特性,有利于扩展和维护. 在程序中使用static 变量 1. 局部变量 普通局部变量是再熟悉不过的变量了,在任何一个函数内 ...

  8. Windows11使用WSL Ubuntu搭建paddle的GPU环境

    Windows11使用WSL Ubuntu搭建paddle的GPU环境 最近升级到了Windows11,突然有个大胆的想法:在Windows11上安装WSL,将所有开发环境安装到WSL中.这样就能在w ...

  9. 自定义Lock实现

    1 package com.wyt.lock.test; 2 3 import java.util.concurrent.LinkedBlockingQueue; 4 import java.util ...

  10. Linux系统Shell脚本第二章:条件测试、正整数字符串比较与if、case语句

    目录 一.条件测试 1.三种测试方法 2. 正整数值比较 3.字符串比较 4.逻辑测试 二.脚本中常用命令 1.echo命令 2.date命令 3.cal命令 4.tr命令 5.cut命令 6.sor ...