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. vivado报错vivado 12-8300 launch hls failed please see vivado hls.log for details

    报错: 解决方案: 1. Download the "y2k22_patch-1.2.zip" file attached to this page 2. Unzip the fi ...

  2. python链接数据库

    一.链接数据库 #sql1.py import pymysql # user=input('用户名: ').strip() # pwd=input('密码: ').strip() #链接 # conn ...

  3. Create 1select+jdbc+jsp

    <form action="UserServlet" method="get"> 查询条件:<input type="text&qu ...

  4. Ubuntu 桌面系统升级

    背景 之前在学习 ROS2 时,安装 ros-humble-desktop 出现依赖错误:无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系. 依赖错误 该问题需要升级 Ub ...

  5. 随机颜色,加载loading效果,节流,应用周期函数,wxs

    随机颜色 data: { colorList:[] }, getColor(){ wx.request({ url: 'https://www.escook.cn/api/color', method ...

  6. mysql查询最近2天数据

    SELECT * FROM jk_dzbl_zybrbljlb where jlrq >= now()-interval 2 day

  7. 0627.selenium请求库*2

    昨天已经介绍了关于selenium的简单基本基本使用--通过两种方式自动打开和关闭谷歌浏览器今天,我们将介绍的模块将是在昨天打开谷歌浏览器的基础上,打开某一个电商平台,并搜索某一个产品,利用前面学的知 ...

  8. springmvc 能进入Controller,但是前端页面还是404

    问题现象: 1.Controller里面的方法上已经加了注解 @ResponseBody 2.能进入controller的方法里面: 3.前端返回状态码 404: 4.控制台没有异常信息: 问题原因: ...

  9. Minio服务器搭建

    记录Minio服务器搭建过程 参考 1.下载minio 从地址https://min.io/download#/windows 下载minio server和minio client. 2.将两个ex ...

  10. 51nod 1594 Gcd and Phi

    Link 题解: $ans = \sum_{i = 1}^{n}\sum_{j = 1}^{n}phi(gcd(phi(i), phi(j)))$ $=\sum_{d = 1}^{n}phi(d)\s ...