1.实现效果:
2.实现思路:
首先,angular得把我的旧数据记下来的吧。
angular的双向绑定依赖脏检查机制。为要双向绑定的数据进行注册,注册到$scope上。($scope是angular数据和模型之间的桥梁。)注册到$scope上的$$watchers数组中。其实就是:我把我要监听的对象,我要监听的函数全部写入一个记忆的数组里,以后我要查询我的数据是否改变,我就只需遍历数组,找出储存在数组中的old值,如果new值和old值不同,我就触发数组里的callback函数,来实现我想要的效果。这个数组就是用来记忆我的旧数据和callback。
那么angular使用什么机制来查询我的$$watcher数组呢。
我们发现,在angular封装的指令下,指令触发时,angular会内部调用一个$apply函数。apply函数用来调用$rootScope下的$digest函数。(rootscope是所有scope们的根。一个个scope总得有个数据结构串在一起吧。要不然如何联系。)$degist从rootscope开始逐级遍历各个scope,每个scope遍历$$watchers数组,查询里面的每一个old值和new值是不是相等呀,不相等就认为是脏数据,可以运行callback函数啦,并且更新old数据为new数据。每次遇到脏数据,angular就预测克鞥还会有脏数据,就会一直循环运行下去。
3.实现代码:
1.首先定义Scope类。
它有一个注册监听即添加到$$watchers数组的功能Scope.prototype.$watch
,和一个触发脏检查的功能Scope.prototype.$digest
var Scope=function(){
this.$$watchers = [];
}
Scope.prototype.$watch=function(watchExp,listeners){
}
Scope.prototype.$digest=function(){
}
2.充实一下:
var Scope=function(){
this.$$watchers = [];
}
Scope.prototype.$watch=function(watchExp,listeners){
this.$$watchers.push({
watchExp:watchExp,listeners:listeners||function(){}
})
}
Scope.prototype.$digest=function(){
var dirty;
do{
dirty=false;
for(var i = 0,len = this.$$watchers.length;i < len;i ++ ){
var newValue=this.$$watchers[i].watchExp();
var oldValue=this.$$watchers[i].last;
if(oldValue !== newValue){
dirty=true;
this.$$watchers[i].last=newValue;
this.$$watchers[i].listeners(newValue,oldValue);
}
}
}while(dirty);
}
3.html标签
<input type="text" id="input">
<p id="display"></p>
4.实例化和调用
先实例化一波
var $scope=new Scope();
首先,我们在input标签触发onchange事件的时候,我们去$digist
一下$scope
的$$watcher
数组,要找到我们要存储的值。
那么我们就要在初始化的时候,在$$watcher
里面注册一个值和它的watchEXP函数(这个用来拿到最新数据)和callback函数。
现在我们在scope里定义一个name
变量。我们决定在watcher中监听它,在onchange事件中维护它。
onchange中我们根据input的onchange事件,把input的值赋值给scope中的name
变量。(好了现在这个那么更新了,就等$digist
检查到它了。)
我们在watchEXP中返回new值:name
变量。我们在callback事件中(即digest事件要触发的事件)把name值赋值给p的value。
$scope.name="liuchen";
var input=document.querySelector('#input');
var display=document.querySelector('#display');
input.onchange=function() {
$scope.name=input.value;
$scope.$digest();
}
$scope.$watch(function(){
return $scope.name
},function(){
display.innerText=$scope.name;
})
5.好难形容啊,看代码把
<input type="text" id="input">
<p id="display"></p>
<script>
var Scope=function(){
this.$$watchers = [];
}
Scope.prototype.$watch=function(watchExp,oldValue);
}
}
}while(dirty);
}
var $scope=new Scope();
$scope.name="liuchen";
var input=document.querySelector('#input');
var display=document.querySelector('#display');
input.onchange=function() {
$scope.name=input.value;
$scope.$digest();
}
$scope.$watch(function(){
return $scope.name
},function(){
display.innerText=$scope.name;
})
</script>
数据改了一个地方,却要遍历所有$$watchers
的所有数据,如果项目很大的话,性能是不是有点低下了呢。。。。。