了解 Object.defineProperty API
首先,我们应该了解一下 JS
中的一个 API
:
Object.defineProperty(object, propertyname, descriptor)
该方法的作用:将属性添加到对象,或者修改现有属性的特性
通常情况下,我们添加一个属性在对象上会这样写:
1 | const obj = {} |
Object.defineProperty
也同样能做到:
1 | // 使用 Object.defineProperty 增加属性 |
这样做虽然增加了代码量,但却可以控制对象属性的读取值,执行上面代码:
1 | obj.name |
封装 defineReactive 函数
对 Object.defineProperty
进行封装,方便调用:
1 | // defineReactive 函数封装 |
defineReactive
函数简陋的实现了Vue里的响应式原理,即在get
方法中收集依赖,在set
方法中触发依赖,更新视图。
defineReactive
函数的调用:
1 | const obj = {} |
添加的依赖函数,将在Object.defineProperty
的get
方法中被收集,所以在调用obj.name
时会将新的依赖添加到依赖数组里,在调用obj.name = xx
时会触发依赖列表。
Vue 中将 data 变为可观察 (observable) 的
下面的代码简单的说明了如何把 data 的属性转化为可观察的。
1 | const observable = (obj, cb) => { |
此时要触发视图的更新(set
方法),需要使用app._data.name
,但为了简便易懂,我们更希望使用 app.name
这样的方式直接触发set
对视图进行重绘,那么我们就需要用到代理。
代理
代理函数,将 data 里的属性移植到 vue实例中去,采用 app.name 这种方式触发 set,而非 app._data.name
1 | function _proxy(data) { |
在 class Vue
的 constructor
中使用_proxy(ops.data)
,完成代理即可使用 app.name
触发 set
更新视图。