zoukankan      html  css  js  c++  java
  • knockout.js的学习笔记4

    本节对第三节的代码进行重构一下。

    我们发现$.computed其实也是一种$.observable,因此可以写成这样:

                var validValueType = $.oneObject("Null,NaN,Undefined,Boolean,Number,String")
                $.dependencyChain = (function () {
                    var _frames = [];
                    return {
                        begin: function (ret) {
                            _frames.push(ret);
                        },
                        end: function () {
                            _frames.pop();
                        },
                        collect: function (self) {
                            if (_frames.length > 0) {
                                self.list = self.list || [];
                                var fn = _frames[_frames.length - 1];
                                if ( self.list.indexOf( fn ) >= 0)
                                    return;
                                self.list.push(fn);
                            }
                        }
                    };
                })();
                $.notifyUpdate = function(observable){
                    var list = observable.list
                    if($.type(list,"Array")){
                        for(var i = 0, el; el = list[i++];){
                            el();//通知顶层的computed更新自身
                        }
                    }
                }
                $.computed = function(obj, scope){
                    var args//构建一个至少拥有getter,scope属性的对象
                    if(typeof obj == "function"){
                        args = {
                            getter: obj,
                            scope: scope
                        }
                    }else if( typeof obj == "object" && obj && obj.getter){
                        args = obj
                    }
                    return $.observable(args, true)
                }
    
                $.observable = function(old, isComputed){
                    var cur, getter, setter, scope
                    function ret(neo){
                        var set;//判定是读方法还是写方法
                        if(arguments.length){ //setter
                            neo =  typeof setter === "function" ? setter.call( scope, neo ) : neo
                            set = true;
                        }else{  //getter
                            if(typeof getter === "function"){
                                $.dependencyChain.begin(ret);//只有computed才在依赖链中暴露自身
                                neo = getter.call( scope )
                                console.log(neo+"!!!!!!!!!!")//用来查看执行情况
                                $.dependencyChain.end()
                            }else{
                                neo = cur
                            }
                            $.dependencyChain.collect(ret)//将暴露到依赖链的computed放到自己的通知列表中
                        }
                        if(cur !== neo ){
                            cur = neo;
                            $.notifyUpdate(ret)
                        }
                        return set ? ret : cur
                    }
                    if( isComputed == true){
                        getter = old.getter;  setter = old.setter; scope  = old.scope;
                        ret();//必须先执行一次
                    }else{
                        old = validValueType[$.type(old)] ? old : void 0;
                        cur = old;//将上一次的传参保存到cur中,ret与它构成闭包
                        ret(old);//必须先执行一次
                    }
                    return ret
                }
    
                function MyViewModel() {
                    this.firstName = $.observable('Planet');
                    this.lastName = $.observable('Earth');
    
                    this.fullName = $.computed({
                        getter: function () {
                            return this.firstName() + " " + this.lastName();
                        },
                        setter: function (value) {
                            var lastSpacePos = value.lastIndexOf(" ");
                            if (lastSpacePos > 0) { // Ignore values with no space character
                                this.firstName(value.substring(0, lastSpacePos)); // Update "firstName"
                                this.lastName(value.substring(lastSpacePos + 1)); // Update "lastName"
                            }
                        },
                        scope: this
                    });
                    this.card = $.computed(function(){
                        return this.fullName() +" 屌丝"
                    },this);
                    this.wordcard = $.computed(function(){
                        return this.card() +"工作卡 "
                    },this)
                    this.wordcardA = $.computed(function(){
                        return this.wordcard() +"A "
                    },this)
                }
    
                window.onload = function(){
                    var model = new MyViewModel();
    
                    $.log("==================")
                    model.lastName("last");
                    $.log("==================")
    
                }
    

    打印如下:

    Planet Earth 屌丝!!!!!!!!!!
    Planet Earth 屌丝工作卡 !!!!!!!!!!
    Planet Earth!!!!!!!!!!
    Planet Earth 屌丝!!!!!!!!!!
    Planet Earth 屌丝工作卡 !!!!!!!!!!
    Planet Earth 屌丝工作卡 A !!!!!!!!!!
    ==================
    Planet last!!!!!!!!!!
    Planet last!!!!!!!!!!
    Planet last 屌丝!!!!!!!!!!
    Planet last!!!!!!!!!!
    Planet last 屌丝!!!!!!!!!!
    Planet last 屌丝工作卡 !!!!!!!!!!
    Planet last!!!!!!!!!!
    Planet last 屌丝!!!!!!!!!!
    Planet last 屌丝工作卡 !!!!!!!!!!
    Planet last 屌丝工作卡 A !!!!!!!!!!
    ==================
    

    依赖链发生效力了!不过感觉糟极了,有许多通知是没必要的。我们在$.notifyUpdate与$.observable添加缓存机制看看:

     $.notifyUpdate = function(observable){
                    var list = observable.list;
                    if($.type(list,"Array")){
                        for(var i = 0, el; el = list[i++];){
                            delete el.cache;//清除缓存
                            el();//通知顶层的computed更新自身
                        }
                    }
                }
    //**********************略***************  
     $.observable = function(old, isComputed){
    //**********************略***************  
     function ret(neo){
                        var set;//判定是读方法还是写方法
                        if(arguments.length){ //setter
                            neo =  typeof setter === "function" ? setter.apply( scope, arguments ) : neo
                            set = true;
                        }else{  //getter
                            if(typeof getter === "function"){
                                $.dependencyChain.begin(ret);//只有computed才在依赖链中暴露自身
                                if("cache" in ret){
                                    neo = ret.cache;//从缓存中读取,防止递归
                                }else{
                                    neo = getter.call( scope );
                                    ret.cache = neo;//保存到缓存
                                    console.log(neo+"!!!!!!!!!!");//
                                }
                                $.dependencyChain.end()
                            }else{
                                neo = cur
                            }
                            $.dependencyChain.collect(ret)//将暴露到依赖链的computed放到自己的通知列表中
                        }
                        if(cur !== neo ){
                            cur = neo;
                            $.notifyUpdate(ret);
                        }
                        return set ? ret : cur
                    }
    //**********************略***************  
                    if( isComputed == true){
                        getter = old.getter;  setter = old.setter; scope  = old.scope;
                        ret();//必须先执行一次
                    }else{
                        old = validValueType[$.type(old)] ? old : void 0;
                        cur = old;//将上一次的传参保存到cur中,ret与它构成闭包
                        ret(old);//必须先执行一次
                    }
                    return ret
    }
    

    这时它的情况就好多了:

    Planet
    Earth
    Planet Earth!!!!!!!!!!
    Planet Earth 屌丝!!!!!!!!!!
    Planet Earth 屌丝工作卡 !!!!!!!!!!
    Planet Earth 屌丝工作卡 A !!!!!!!!!!
    ==================
    Planet last!!!!!!!!!!
    Planet last 屌丝!!!!!!!!!!
    Planet last 屌丝工作卡 !!!!!!!!!!
    Planet last 屌丝工作卡 A !!!!!!!!!!
    ==================
    
  • 相关阅读:
    How To Build CyanogenMod Android for smartphone
    CentOS安装Code::Blocks
    How to Dual boot Multiple ROMs on Your Android SmartPhone (Upto Five Roms)?
    Audacious——Linux音乐播放器
    How to Dual Boot Multiple ROMs on Your Android Phone
    Everything You Need to Know About Rooting Your Android Phone
    How to Flash a ROM to Your Android Phone
    什么是NANDroid,如何加载NANDroid备份?
    Have you considered compiled a batman-adv.ko for android?
    BATMAN—Better Approach To Mobile Adhoc Networking (B.A.T.M.A.N.)
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/2554133.html
Copyright © 2011-2022 走看看