最近在重新梳理知识点,Vue写了那么久, 是时候给自己一个交代了.也不能每天画好玩的UI对吧.
从题目开始, 这篇文章的前置知识点有
Object.defineProperty
关于第一个Object.defineProperty我已经给了链接.
这个方法可以让我们自定义对象上属性的属性.
有点绕啊.举个例子
1 | var obj = { |
这个方法相关的我们就复习完了.
响应式
先说定义, 通俗一点说的响应式是指, 当数据a变化了, 与这个数据a相关的操作都会更新. 来看个非响应式的例子可能会好理解一点.(反向操作)
1 | let a = 1; |
那么怎么做到这一点?
我们监测变量a, 如果a触发了get操作, 那么很可能,进行了依赖性的运算, 在这个例子里就是
1 | let b = a * 5 |
在这里b的计算依赖于a.噢, 所以,在这个地方我们获取了a, 并进行了计算, 那我就拿个小本子把这个操作记下来.
如果, 变量a触发了set操作, 也就是赋值操作, 那么我们就要拿出小本子, 在把上面记下来的依赖重新执行一遍就好.
其实这就是响应式的原理.
- 收集依赖
- 侦测变化
- 触发更新
之前我们也提到了, defineProperty我们通过get方法知道什么时候收集依赖, 通过set方法知道什么时候发生了变化, 触发更新.
接下来就是实操了.
把对象所有的属性转换为get/set
defineProperty不像proxy,它只能单个的去监听对象上的属性,而proxy这个小玩具.就很有意思.
那么请听题: 假设你有一个对象(你在骗自己), 你希望有一个函数, 这个函数把这个对象上所有的属性转换为可监测get/set。如果触发了get需要在控制台输出
1 | `get: ${key}: ${value}` |
一定要自己试一下.以下是答案
1 | const transform = (obj, i) => { |
Vue中的依赖跟踪

每个vue的实例都会有一个watcher对象,这个对象中提供增加依赖和触发依赖更新的方法。
在getter操作时把依赖传入Watcher, 而在单个属性发生改变,也就是set的时候触发依赖更新notify, 继而Watcher执行视图更新操作。
注意, 在这里用了设计模式中的
发布-订阅模式
每个vue实例就是订阅者, 这些订阅者的更新事件都放到watcher对象里管理。当我们增加一个依赖项的时候把依赖项放入订阅队列, 然后在每次更新的时候区触发对应的事件。完成更新
来看代码
1 | // 一个依赖项就是一个watch |
使用get/set方法与依赖收集更新结合, 完成小型的观察者模式
这个可以先自己实现后再往下看.啊?没时间啊?没关系啊, 就…就点收藏就行了啊.
1 | // 2. 依赖项 |
看懂的时候觉得真的, 尤雨溪太他妈帅了。这东西写得好精巧啊。
总结
重新理一下,如果你要做到响应式.那么你应该有什么?
- 你要有监测机制, 因为如果你不知道什么时候改变,那么你就不会知道啥时候响应
- 你要有依赖收集, 因为你不能预知依赖到底有多少, 那么你就得管理依赖项
- 你要有响应机制, 你检测到了更新, 继而触发依赖收集, 下一步就是在数据更新的时候, 根据收集到的依赖, 去触发响应, 更新依赖项
以上这三点, 的实现分别为:
- 检测机制用 get/set方法进行检测, 作为依赖收集, 触发响应的事件分发点
- 依赖收集和响应机制我们使用dep这个类来完成, 供检测机制调用
- 使用autorun包裹存在依赖的操作, 并生成引用, 供dep类的getDep依赖收
完结, 撒花, 满地打滚求点赞.