好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

knockout.js的学习笔记4

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 !!!!!!!!!!

==================

 

 

标签:  javascript ,  mass

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于knockout.js的学习笔记4的详细内容...

  阅读:48次