knockout.js的學習筆記4

來源:互聯網
上載者:User

本節對第三節的代碼進行重構一下。

我們發現$.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}

這時它的情況就好多了:

PlanetEarthPlanet Earth!!!!!!!!!!Planet Earth 屌絲!!!!!!!!!!Planet Earth 屌絲工作卡 !!!!!!!!!!Planet Earth 屌絲工作卡 A !!!!!!!!!!==================Planet last!!!!!!!!!!Planet last 屌絲!!!!!!!!!!Planet last 屌絲工作卡 !!!!!!!!!!Planet last 屌絲工作卡 A !!!!!!!!!!==================

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.