使用脏检查机制实现数据的双向绑定

1.实现效果:

这里写图片描述

input标签的值一变化,底下的p标签的内容就跟着变化。

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,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);
      }
      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的所有数据,如果项目很大的话,性能是不是有点低下了呢。。。。。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值