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

前端之家收集整理的这篇文章主要介绍了使用脏检查机制实现数据的双向绑定前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

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

猜你在找的Angularjs相关文章