一篇文章搞懂Vue2框架双向绑定的实现原理
Vue2框架双向绑定的实现原理
双向绑定的基本概念
在Vue2框架中,双向绑定是指视图层和数据层之间的自动同步。当视图层中的数据发生变化时,数据层中的数据也会随之变化;反之,当数据层中的数据发生变化时,视图层中的数据也会随之变化。
双向绑定的实现原理
Vue2框架中的双向绑定是通过数据劫持和发布-订阅模式来实现的。
数据劫持
Vue2框架中的数据劫持是通过Object.defineProperty()方法来实现的。该方法可以监听一个对象的属性,并在属性值发生变化时触发相应的回调函数。具体来说,Vue2框架会将数据层中的每个属性都转化为getter和setter方法,当视图层读取或修改这些属性时,就会触发相应的getter或setter方法,从而实现数据的监听和同步。
例如,假设有一个Vue实例,其中有一个data属性,如下所示:
var vm = new Vue({
data: {
message: 'Hello Vue!'
}
})
在这个例子中,message属性被转化为getter和setter方法,如下所示:
var data = {
message: 'Hello Vue!'
}
Object.defineProperty(data, 'message', {
get: function () {
console.log('getter被调用了')
return this._message
},
set: function (newValue) {
console.log('setter被调用了')
this._message = newValue
}
})
data.message // 输出:getter被调用了 Hello Vue!
data.message = 'Hello World!' // 输出:setter被调用了
从上述代码可以看出,当我们读取或修改message属性时,会分别触发相应的getter和setter方法。
发布-订阅模式
Vue2框架中的发布-订阅模式是通过一个事件中心来实现的。该事件中心负责管理所有的事件和相应的回调函数,当某个事件被触发时,事件中心会自动调用相应的回调函数。
在Vue2框架中,事件中心被封装在Dep类中。每个数据属性都会对应一个Dep实例,当该属性被读取或修改时,就会触发相应的getter或setter方法,并通知Dep实例,从而实现数据的自动同步。
例如,假设有一个Vue实例,其中有一个data属性,如下所示:
var vm = new Vue({
data: {
message: 'Hello Vue!'
}
})
在这个例子中,message属性对应的Dep实例如下所示:
function Dep() {
this.subs = []
}
Dep.prototype.addSub = function (sub) {
this.subs.push(sub)
}
Dep.prototype.notify = function () {
this.subs.forEach(function (sub) {
sub.update()
})
}
var data = {
message: 'Hello Vue!'
}
Object.defineProperty(data, 'message', {
get: function () {
console.log('getter被调用了')
if (Dep.target) {
Dep.target.addDep(this.dep)
}
return this._message
},
set: function (newValue) {
console.log('setter被调用了')
this._message = newValue
this.dep.notify()
}
})
data.dep = new Dep()
var watcher = {
update: function () {
console.log('视图层更新了')
}
}
Dep.target = watcher
data.message // 输出:getter被调用了
Dep.target = null
data.message = 'Hello World!' // 输出:setter被调用了 视图层更新了
从上述代码可以看出,当我们读取或修改message属性时,会触发相应的getter或setter方法,并通知对应的Dep实例。该Dep实例会自动调用所有订阅了该属性的Watcher实例的update()方法,从而实现视图层和数据层之间的自动同步。
举例说明
假设有一个Vue实例,其中有一个message属性和一个input元素,如下所示:
<div id="app">
<input type="text" v-model="message">
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
在这个例子中,当我们在input元素中输入文字时,该文字会自动同步到message属性中;反之,当我们修改message属性时,input元素中的文字也会自动更新。
这种自动同步的机制是通过Vue2框架的双向绑定实现的。具体来说,当我们在input元素中输入文字时,会触发相应的input事件,从而自动修改message属性;反之,当我们修改message属性时,会触发相应的setter方法,从而自动更新input元素中的文字。
总结
Vue2框架的双向绑定是通过数据劫持和发布-订阅模式来实现的。数据劫持可以监听数据层中的属性,从而实现数据的自动同步;发布-订阅模式可以管理所有的事件和相应的回调函数,从而实现视图层和数据层之间的自动同步。这种自动同步的机制使得开发者可以更加方便地管理数据和视图。
转载自:https://juejin.cn/post/7240004799721209917