简单的响应
给定 a 和 b 两个参数,要求无论 a 如何变化,b 永远等于 a 的 10 倍,如何实现?
即如下效果:
1 | let a = 3 |
在每次改变 a 的值之后手动更新 b 的值,这是山顶洞人的做法,我们想要的是 a 的值改变之后,自动执行 b 的改变函数。
我们可以维护一个 state 对象:
1 | state = { |
然后每次 a 发生变化时执行:
1 | onStateChanged(() => { |
要实现这个很简单,我们可以每次改变 a 的值从原来的直接赋值变为调用一个函数:
1 | setState({ a: 5}) |
在 setState
这个函数里做赋值操作,同时执行 onStateChanged
函数使 b 的值自动得到更新。
完整的实现如下:
1 | let update |
严格来说应该把 state
,update
,onStateChanged
,setState
封装起来,当初始化值之后,只允许通过 setState
来改变变量的值。这其实已经有点像 react 了。
使用 Object.defineProperty
这里用到一个对象方法 Object.defineProperty
,目的是将 data
对象里的所有属性通过这个方法来重新定义,重写属性的修改(setter
)方法。
1 | // 初始化 data 对象 |
vue 的响应
使用 Object.defineProperty
方法已经和 vue 的实现有点接近了,vue 实例是将 data
对象里的所有属性通过这个方法来重新定义,实现属性被访问(getter
)和修改(setter
)时通知(Notify
)变化(Watcher
调用函数)。
即实现如下功能:
1 | const data = { |
具体的实现:
1 | // 在全局定义一个 Watch 类 |
上面的 triggerFunction
只是简单地 console.log
出 a
的值,其实可以进一步地实现 re-render
函数,使得页面的 html
元素也自动重新渲染,便是完整的 vue 响应了。