Vue数据双向绑定的原理解析
思路
所谓MVVM数据双向绑定,即主要是:数据变化更新视图,视图变化更新数据。如图
也就是说,输入框内容变化时,data 中的数据同步变化。即 view —> model 的变化。data 中的数据变化时,文本节点的内容同步变化。即 model —> view 的变化
原理
Vue 实现的双向数据绑定,是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。要实现mvvm的双向绑定,就必须要实现以下几点:
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象
1. 实现一个数据监听器 Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
2. 实现一个指令解析器 Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
3. 实现一个 Watcher,作为连接 Observer 和 Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
4. 将 MVVM 作为数据绑定的入口,整合 Observer,Compile 和 Watcher 三者
实现简单的双向绑定数据
<body>
<input type="text" id="inp">
<div id="demo"></div>
<script>
var demo = document.querySelector('#demo')
var inp = document.querySelector('#inp')
let obj = {}
inp.addEventListener('input', function(e) {
// 给 obj 的 name 属性赋值,进而触发该属性的 set 方法
obj.name = e.target.value
})
Object.defineProperty(obj, 'name', {
set: function(newVal) {
inp.value = newVal
demo.innerHTML = newVal
console.log('更新了obj的name:' + newVal) // name 属性值被修改时触发
},
get: function() {
console.log('获取obj数据name')
}
})
obj.name // 获取 data 数据 name
</script>
</body>