一、我们先来一个简单的实现双向数据驱动的小例子:
1、html部分:
<div id="app">
<input type="text" id="txt">
<h2 id="show"></h2>
</div>
2、js部分
var data = {}
Object.defineProperty(data, 'txt', {
get: function () {
return data
},
set: function (newVal) {
document.getElementById('txt').value = newVal
document.getElementById('show').innerHTML = newVal
}
})
document.addEventListener('keyup', function (e) {
data.txt = e.target.value
})
3、效果如下:
上面我们用到 Object.defineProperty() 方法,这是用来添加一个新属性或者修改一个已有属性,当我们访问或者修改一个对象的属性时,不是仅仅找到该属性名并进行操作那么简单,如data.txt,这实际上是调用了 getter 隐藏函数(有点像方法调用),从而获取到data对象中属性名为txt的值;同样道理,当修改属性时是调用了 setter 方法(详解可以查看 《你不知道的JavaScript 上卷》 第3章)。
二、Vue数据双向绑定的原理
当我们把一个 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。虽然 getter/setter 是隐藏函数,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
在 Vue 中通常把 MVVM 作为数据绑定的入口,整合 Observer (数据观察者),Compile (编译) 和 Watcher (数据订阅者) 三者,通过 Observer 来监听自己的 model 的数据变化,通过 Compile 来解析编译模板指令( vue 中是用来解析 {{}}),最终利用 watcher 搭起 observer 和 Compile 之间的通信桥梁,从而达到 数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。
后面我们会细讲Observer、Compile、watcher 以及 Dep 之间是怎样联系的