• angular1脏值监测 模拟实现


    /*
    *
    */
    
    function Scope(){
        this.$$watchers = [];
    }
    //valueEq为真时,基于值的检查开启。
    Scope.prototype.$watch = function(watchFn, listenerFn, valueEq){
        var watcher = {
            watchFn: watchFn,
            listenerFn: listenerFn || function() {},
            valueEq: !!valueEq
        };
        this.$$watchers.push(watcher);
    }
    
    Scope.prototype.$digestOnce = function(){
        var self = this;
        var dirty;
        _.forEach(this.$$watchers,function(watch){
            var newValue = watch.watchFn(self);
            var oldValue = watch.last;
            if(newValue !== oldValue){
                watch.listenerFn(newValue, oldValue, self);
                dirty = true;
            }
            watch.last = (watch.valueEq ? _.cloneDeep(newValue) : newValue);
        });
        return dirty;
    }
    
    Scope.prototype.$digest = function(){
        var ttl = 10;
        var dirty;
        do{
            dirty = this.$$digestOnce();
            if(dirty && !(ttl--)){
                throw "10 digest iterations reached";
            }
        }while(dirty);
    }
    
    //值相等检测函数
    Scope.prototype.$$areEqual = function(newValue, oldValue, valueEq){
        if(valueEq){
            return _.isEqual(newValue, oldValue);//如果是对象或数组,递归按值比较
        }else{
            return newValue === oldValue ||
                (typeof newValue === 'number' && typeof oldValue === 'number'
                    && isNaN(newValue) && isNaN(oldValue));//非数字(NaN判断)
        }
    }
    
    Scope.prototype.$eval = function(expr, locals){
        return expr(this, locals);
    }
    
    Scope.prototype.$apply = function(expr){
        try{
            return this.$eval(expr);
    
        }finally{
            this.$digest();
        }
    }
    
    var scope = new Scope();
    scope.firstName = 'Joe';
    scope.counter = 0;
    
    scope.$watch(
        function(scope){
            return scope.counter;
        },
        function(newValue, oldValue, scope){
            scope.counterIsTwo = (newValue ===2);
        }
    );
    scope.$watch(
        function(scope){
            return scope.firstName;
        },
        function(newValue, oldValue, scope){
            scope.counter++;
        }
    );
    
    //After the first digest the counter is 1
    scope.$digest();
    console.assert(scope.counter === 1);//正确
    
    // On the next change the counter becomes two, and the other watch listener is also run because of the dirty check
    scope.firstName = 'Jane';
    scope.$digest();
    console.assert(scope.counter === 2);//正确
    console.assert(scope.counterIsTwo);//正确
    http://teropa.info/blog/2013/11/03/make-your-own-angular-part-1-scopes-and-digest.html
    https://github.com/spring-fe/angular1x
  • 相关阅读:
    Application failure. hr=0x80040101:Failed to initialize virtual machine.
    windows无法配置此无线连接的无线网络
    IOS测试覆盖率生成(XCode 4.6)
    使用TopCoder的方法
    VC中自动为项目增加版本信息
    Android杂谈ListView之ArrayAdapter的使用
    Android杂谈ListView之SimpleAdapter的使用
    Android美工坊.9.png格式图片的制作与使用1
    Android杂谈layout的横竖屏处理
    Android杂谈ListView之BaseAdapter的使用
  • 原文地址:https://www.cnblogs.com/fe-huahai/p/6421909.html
Copyright © 2020-2023  润新知