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

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 是一个JavaScript 框架。它可通过 注:建议把脚本放在 元素的底部。这会提高网页加载速度,因...
angluarjs中页面初始化的时候会出现语法{{}}在页面中问题,也即是页面闪烁问题。出现这个的原因是:由于...
AngularJS 通过被称为指令的新属性来扩展 HTML。AngularJS 指令AngularJS 指令是扩展的 HTML 属性,带有...
AngularJS 使用表达式把数据绑定到 HTML。AngularJS 表达式AngularJS 表达式写在双大括号内:{{ expres...
ng-repeat 指令可以完美的显示表格。在表格中显示数据 {{ x.Name }} {{ x.Country }} 使用 CSS 样式为了...
$http是 AngularJS 中的一个核心服务,用于读取远程服务器的数据。读取 JSON 文件下是存储在web服务器上...