一、Angular中的双向数据绑定(脏检查机制):
AngularJs 为 scope 模型上设置了一个 监听队列,用来监听数据变化并更新 view 。每次绑定一个东西到 view(html) 上时 AngularJs 就会往 $watch 队列里插入一条 $watch,用来检测它监视的 model 里是否有变化的东西。当浏览器接收到可以被 angular context 处理的事件时,$digest 循环就会触发。$digest 会遍历所有的 $watch。从而更新DOM。
$watch
这有点类似于我们的观察者模式,在当前作用域 s c o p e 下 , 我 们 创 建 一 个 监 控 器 scope下,我们创建一个监控器 scope下,我们创建一个监控器watchers和一个监听器 w a t c h , watch, watch,watchers 负责管理所有的 w a t c h , 当 我 们 每 次 绑 定 到 U I 上 的 时 候 就 自 动 创 建 一 个 watch,当我们每次绑定到UI上的时候就自动创建一个 watch,当我们每次绑定到UI上的时候就自动创建一个watch,并把它放到 $watchers。
app.controller('MainCtrl', function($scope) {
$scope.Hello = "Hello";
$scope.world = "World";
});
<div>{{Hello}}</div>
这里,即便我们在 s c o p e 上 添 加 了 两 个 变 量 , 但 是 只 有 一 个 scope上添加了两个变量,但是只有一个 scope上添加了两个变量,但是只有一个scope.Hello绑定在了UI上,因此在这里只生成了一个$watch
$digest
当浏览器接收到可以被angular context处理的事件时, d i g e s t 循 环 就 会 触 发 。 digest循环就会触发。 digest循环就会触发。digest将会遍历我们的 w a t c h , 如 果 watch,如果 watch,如果watch没有变化,这个循环检测就将停止,如果有至少一个更新过,这个循环就会再次触发,直到所有的$watch都没有变化。这样就能够保证每个model都已经不会再变化。这就是脏检查(Dirty Checking)机制
model修改一次至少要触发两次循环检查,第一次发现有 $watch 修改,再循环一次,发现无修改了才停止。
Angular中的双向数据绑定内容引用来自:
作者:Nickyzhang
链接:https://www.jianshu.com/p/ad0c48810bf1
来源:简书
二、Vue中的双向数据绑定(数据劫持)
Vue双向数据绑定的核心是使用Object.defineProperty(),劫持各个属性的getter和setter,在数据模型变化的时候,发布消息给订阅者(绑定了数据模型的DOM元素),触发相应的监听回调。
数据劫持-Observer:
<body>
<input type="text" id="demo"/>
<div id="show"></div>
<script>
var odiv = document.getElementById('show');
var oinput = document.getElementById('demo');
var oData = {
valueObj: {
value: 'grandma',
name: 'zhang'
}
};
oinput.oninput = function(){
oData.valueObj.value = this.value;
}
function upDate (){
odiv.innerText = oData.valueObj.value;
}
upDate();
//监控对象的某个属性是否发生改变
function Observer (data){
if(!data || typeof data != 'object'){
return data;
}
// for(var prop in data){
// }
Object.keys(data).forEach(function(key){
definedRective(data, key, data[key]);
});
}
function definedRective(data, key, val){
Observer(val);
Object.defineProperty(data, key,{
get (){
return val;
},
set (newValue) {
if(newValue == val){
return;
}
upDate();
}
});
};
Observer(oData);
oData.valueObj.value = 'haha';
</script>
</body>