前天面试被面试官问到了 "vue 实现双向数据绑定的原理是什么?",除了知道v-modle可以实现数据双向绑定,我哪里知道其中的原理。面试已凉,回来之后查阅了资料,写下这篇博客,加深自己学习理解,也希望能帮到大家。
VUE是采用数据劫持结合发布者-订阅者模式的方式实现数据双向绑定,通过Object.defineProperty() 来劫持各个属性的setter, getter, 在数据变动时发布消息给订阅者,触发相应的监听回调。
实现原理: 利用了 Object.defineProperty() 方法 重新定义了对象获取属性值(get) 和 设置属性值 (set) 的操作来实现的(对Object.defineProperty()方法不是很了解的我在文章底部也做了补充说明)。它接受3个参数,要操作的对象、要定义或修改的属性名、属性描述符。重点在属性描述符,属性描述符有两种形式:数据描述符和存取描述符。前面说的 get 和 set 就是属于存取描述符的属性
底层就是Object.defineProperty(),get 就是读取之前的旧数据,set 中如果发现数据没改,直接return 原始值;如果改了就直接修改为NewValue。
下面是一个简单的数据双向绑定的实现:
<body>
<div id="app">
<input type="text" id="model"><br />
<div id="modelText"></div>
</div>
<script>
var model = document.getElementById('model')
var text = document.getElementById('modelText')
var content = ''
model.value = content
var obj = {}
Object.defineProperty(obj, 'msg', {
get: function () {
console.log('get')
return content
},
set: function (value) {
content = value
model.value = value
console.log(value)
text.innerHTML = value
}
})
obj.msg = 'please input...'
var isEnd = true
model.addEventListener('keyup', function () {
if (isEnd) {
obj.msg = this.value
}
}, false)
</script>
</body>
你也可以在后面加上中文监听输入和结束:
model.addEventListener('compositionstart', function () {
console.log('start to input Chines