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

    本节换一种方式解读,把我消化过的东西反刍出来可能这样大家容易理解些,knockout.js大量使用闭包,非常难读。

    我们从viewModel看起:

    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
          });
      }
      var a = new MyViewModel();
      a.fullName("xxx yyy")

    这里包含两种observable,没有依赖的与有依赖的,有依赖的通过没有依赖的计算出来,因此叫做computed!

    但不管怎么样,它们都是返回一个函数,我们通过如下代码就可以模拟它们了:

    //注:这里会用到mass Framework的种子模块的API https://github.com/RubyLouvre/mass-Framework/blob/master/src/mass.js
     //observable的传参必须是基本类型
     var validValueType = $.oneObject("Null,NaN,Undefined,Boolean,Number,String");
    $.observable = function(value){
         var v = value;//将上一次的传参保存到v中,ret与它构成闭包
         function ret(neo){
             if(arguments.length){ //setter
                 if(!validValueType[$.type(neo)]){
                     $.error("arguments must be primitive type!")
                     return ret
                 }
                 if(v !== neo ){
                     v = neo;
                 }
                 return ret;
             }else{                //getter
                 return v;
             }
         }
         value = validValueType[$.type(value)] ? value : void 0;
         ret(arguments[0]);//必须先执行一次
         return ret
     }
     
     $.computed = function(obj, scope){//为一个惰性函数,会重写自身
         //computed是由多个$.observable组成
         var getter, setter
         if(typeof obj == "function"){
             getter = obj
         }else if(obj && typeof obj == "object"){
             getter = obj.getter;
             setter = obj.setter;
             scope  = obj.scope;
         }
         var v
         var ret = function(neo){
             if(arguments.length ){
                 if(typeof setter == "function"){//setter不一定存在的
                     if(!validValueType[$.type(neo)]){
                         $.error("arguments must be primitive type!")
                         return ret
                     }
                     if(v !== neo ){
                         setter.call(scope, neo);
                         v = neo;
                     }
                 }
                 return ret;
             }else{
                 v = getter.call(scope);
                 return v;
             }
         }
         ret(); //必须先执行一次
         return ret;
     }

    因此当我们执行new MyViewModel(),就会依次执行$.observable, $.observable, $.computed, $.computed中的参数的getter, getter再调用两个observable。

    问题来了,当我们调用computed时,总会通知其依赖(即firstName ,lastName)进行更新,但firstName 发生改变时没有手段通知fullName 进行更新。ko把这逻辑写在dependencyDetection模块中。我简化如下:

    $.dependencyDetection = (function () {
        var _frames = [];
        return {
            begin: function (ret) {
                _frames.push(ret);
            },
            end: function () {
                _frames.pop();
            },
            collect: function (self) {
                if (_frames.length > 0) {
                    if(!self.list)
                        self.list = [];
                    var fn = _frames[_frames.length - 1];
                    if ( self.list.indexOf( fn ) >= 0)
                        return;
                    self.list.push(fn);
                }
            }
        };
    })();

    我们把它加入到 $.computed 与 $.observable中,再添加一个发布更新函数valueWillMutate

    到这里viewModel中的每个域(firstName, lastName, fullName)只要存在依赖关系都能相互通知了。

     
     
    标签: knockoutjs
  • 相关阅读:
    夺命雷公狗jquery---13css属性操作
    夺命雷公狗jquery---12Class属性操作
    夺命雷公狗jquery---11属性操作
    夺命雷公狗---无限级分类NO7
    夺命雷公狗---无限级分类NO6
    夺命雷公狗---无限级分类NO5
    夺命雷公狗---无限级分类NO4
    夺命雷公狗---无限级分类NO3
    夺命雷公狗---无限级分类NO2
    夺命雷公狗---无限级分类NO1
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2553547.html
Copyright © 2011-2022 走看看