vue双向的双向绑定原理:
基于数据劫持和发布-订阅模式实现的
具体描述:
当vue实例化时,会对数据对象进行递归遍历,利用Object.defineProperty()方法为每个属性生成getter和setter方法,这样当数据发生变化时,setter方法会被触发,通知订阅者去更新视图.而订阅者则是通过Watcher对象进行管理,每个Watcher对象都会在初始化时被添加到对应属性的订阅列表中.当数据变化时,setter方法会通知订阅者,订阅者收到通知会触发update()方法,更新视图.
总结: Vue通过数据劫持和发布-订阅模式实现了双向数据绑定
代码简单实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" id="input">
<span id="span"></span>
</div>
<script type="text/javascript">
var obj = {}
var val = 'hello'
Object.defineProperty(obj, 'hello', {
get: function() {
console.log('get val:', val);
return val
},
set: function(newVal) {
val = newVal
console.log('set val', val);
document.getElementById('input').value = val
document.getElementById('span').innerHTML = val
}
})
document.getElementById('input').addEventListener('keyup', function(e) {
console.log('keyup', obj.hello);
obj.hello = e.target.value
})
</script>
</body>
</html>
上述代码中核心就是Object.defineProperty()方法;
语法:Object.defineProperty(obj, prop, descriptor)
obj: 传入对象
prop: 修改属性的名称
descripttor: 修改属性的描述,也是接收对象;
get获取了val的值,
set方法中把obj.hello的新值给了val,并给span视图更新输入框的值
给输入框注册keyup事件,给obj.hello赋值键盘输入的值
调用obj.hello会触发get函数
给obj.hello赋值会触发set函数
看输出:键盘输入的是1,最先打印的是get方法中的值,后执行的是keyup的输出,最后是set的输出,get输出val的值是hello老的值并未改变;之所以是get输出的是旧的val值,因为我们最先调用的是obj.hello触发的是get,改变val值是在set方法中