美文网首页
动手实现数据双向绑定Angular脏刷新(3)

动手实现数据双向绑定Angular脏刷新(3)

作者: 忧郁的河蟹 | 来源:发表于2015-12-31 12:22 被阅读896次

基本原理

脏刷新基本遵循订阅者设计模式,$watch添加监听者到$$watchers,当执行$degist的时候,读取watchers列表,当发现数值变动的时候,对页面进行刷新,与getter/setter最大的不同有两个地方,1.当数值发生变动的时候,需要主动执行$degist进行主动刷新,2.$degist会扫描监听列表,如果监听列表过长,容易导致性能问题。

代码实现

1.定义$watch函数,记录要监听的属性,并将该属性放到$$watcher监听列表里面。

$watch: function (key, listenerFn) {
  var self = this;
  var watchFn = function (scope) {
    return {value: scope.model[key], key: key};
  }
  
  var watcher = {
    watchFn: watchFn,
    listenerFn: listenerFn || function () {}
  };
  
  this.$$watcher.push(watcher);
}

2.$digest主动数据刷新,函数会读取监听列表里面的元素,新旧数值进行对比,如果发现数据不一样,将会重新渲染。

 $digest: function () {
    var self = this;
    var length = this.$$watcher.length;
    var watcher, newValue, oldvalue, key;
    while(length--){
        watcher = this.$$watcher[length];
        console.log(watcher)
        newValue = watcher.watchFn(this).value;
        key = watcher.watchFn(this).key;
        oldValue = watcher.last;
        if(newValue !== oldValue){
            watcher.last = newValue;
            var arr = self.model2sync[key]
            
            each(arr, function() {
              // 更新节点的text
              this.node.textContent = self.renderStr(this.raw)
            })
         //   var arr = self.model2sync[key]
          //  console.log(arr)
            watcher.listenerFn(newValue, oldValue, this, key);
        }
    }
}

3.改动model数据,主动执行$digest函数,进行脏值检查。

var demo1 = mvvm('#demo1', {
  model: {
    name: 'world',
    time: Date(),
    css: 'green'
  }
});

demo1.$watch('time')

setInterval(function () {
  demo1.model.time = Date();
  demo1.$digest();
}, 1000);

4.完整代码
http://codepen.io/youyudehexie/pen/NxbqPz

对比Getter/Setter的优劣

优点
先来一个重要的例子,列表页刷新。

// 此处是伪代码,renderData 与某个双向绑定模板绑定。
var renderData = [0...1000];
renderData[] = 0; //默认所有数组元素为0.
for (var i = 0; i < 1000; i++) {
      renderData[i] = 1;
}

当我们使用Getter/Setter的时候,实际上,每次修改数值都会激活刷新模版的方法,而脏刷新则可以在完成1000个元素的数值变动后,统一刷新到Dom,只需要刷新1次,显然而见,脏刷新优势巨大。

缺点

  • 当监听元素变多的时候,watcher列表会变得很长,每次都要花费大量的计算,才能找到变动的数据块。
  • 需要主动调用$degist才会刷新,Getter/Setter 方法显得更加智能。

相关文章

网友评论

      本文标题:动手实现数据双向绑定Angular脏刷新(3)

      本文链接:https://www.haomeiwen.com/subject/gznihttx.html