vue.js 采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的 setter 和 getter,在数据变化时发布消息给订阅者,触发相应的监听回调。也就是说数据和视图同步,数据发生变化,视图跟着变化,反之亦然。
当一个 Vue 实例被创建时,它将 data
对象中的所有的 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
由于 JavaScript 的限制,Vue 不能检测数组和对象的变化,因为性能问题(性能代价和获得的用户体验收益不成正比)。
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
此方法接受三个参数:要操作的对象、要定义或修改的对象属性名、属性描述符。
发布者-订阅者模式:订阅者依赖于发布者,当发布者更新时,订阅者将收到通知,并自动更新。(和观察者模式不同的是多了一个事件调度中心)
原生 JS 实现的双向绑定:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>原生双向数据绑定</title>
</head>
<body>
<input type="text" id="inText"/>
<p id="showP"></p>
<script>
let obj = {
data: ''
};
let text = document.getElementById("inText");
let show = document.getElementById("showP");
Object.defineProperty(obj, 'data', {
set: function(val) {
show.textContent = val;
text.value = val;
}
});
obj.data = "hello world!";
text.onkeyup = (event) => {
obj.data = event.target.value;
};
</script>
</body>
</html>
实现效果: