美文网首页
动手实现数据双向绑定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