zoukankan      html  css  js  c++  java
  • Emberjs之ComputedProperty

       计算属性,以下简称CP。简单概括来讲,就是在需要属性值的时候计算一个Function,并将Function返回的值保存在属性中,当第二次获取属性值时,如果发现属性并未改变则直接读取属性,如果属性依赖的事物发生改变,则重新计算该属性值。

    下面用C#实现基本的CP原理(CP其实更复杂一些,但这样一个简单的例子有助于有一个基本的CP理解):

    private object _myCar;                                    // 内部缓存变量
    public bool IsDirty;                                      // MyCar属性依赖的对象
    
    public object MyCar {
        get {
              if(_isDirty) {                                           
                   _myCar = 4S.BuyANewCar('Audio A4');        // 重新计算属性值并保存
              }
              return _myCar;
        }
    }                                        

    文章索引

    JS前端框架之Ember.js系列

    1. What is CP?

      In a nutshell, computed properties let you declare functions as properties. You create one by defining a computed property as a function, which Ember will automatically call when you ask for the property. 

      简而言之,计算属性让你可以把函数方法声明为属性,你通过定义一个计算属性作为函数方法时,Ember将自动调用当访问属性时。

    1. 第一种写法:

    App.Person = Ember.Object.extend({  
      firstName: null,
      lastName: null,
    
      fullName: function() {
        return this.get('firstName') + ' ' + this.get('lastName');
      }.property('firstName', 'lastName')                // fullName是一个依赖属性,当firstName或者lastName发生改变时,并且当访问fullName是,重新执行function,否则返回已缓存的fullName值。
    });
    
    var ironMan = App.Person.create({
      firstName: "Tony",
      lastName:  "Stark"
    });
    
    ironMan.get('fullName'); // "Tony Stark"

    2. 第二种写法:(推荐写法

      CP也可以这样写,建议如下写法,避免“禁用”function的property扩展带来的问题。

      [Prototype Extensions](http://emberjs.com/guides/configuring-ember/disabling-prototype-extensions/)
     fullName: Ember.computed('firstName', 'lastName', function() {
        return this.get('firstName') + ' ' + this.get('lastName');
      })

      Ember.js v1.12 更新带有Set和get方法的CP:

      fullName: Ember.computed("firstName", "lastName", {
        get: function() {
          return this.get("firstName") + " " + this.get("lastName");
        },
        set: function(key, newName) {
          var parts = newName.split(" ");
          this.setProperties({ firstName: parts[0], lastName: parts[1] });
          return newName;
        }
      });

    3. 第三种写法:

      // An array of Ember.Table.Row computed based on `content`
      bodyContent: Ember.computed(function() {
        return RowArrayController.create({
          target: this,
          parentController: this,
          container: this.get('container'),
          itemController: Row,
          content: this.get('content')
        });
      }).property('content.[]', '_reloadBody'),

    2. CP中名词描述定义 

    2.1 CP:Computed Property

    2.2 CP属性:上文例子中的‘fullName’。

    2.3 CP所依赖的源属性:上文例子中的‘firstName’、‘lastName’。

    2.4 CP的回调方法:上文例子中的function(){......}方法。

    2.5 CP属性的Setter/Getter

    3. CP重要原则(特性)

    3.1 只有当获取或设置CP属性时,才可能会触发CP的回调方法,也就是说CP属性是属于‘懒加载’的方式(使用时计算行为)。

    3.2 当CP属性依赖于.property('person.name', 'person.age')时,当person.name、person.age或person本身发生改变时改变(链式依赖)。

    3.3 当CP属性依赖于.property('columns.@each.isLoaded')时:

    • columns里面任何一个元素的isLoaded属性发生变化。
    • columns增加元素或者删除子元素。
    • columns数组本身被重新赋值。
    • 不能依赖@each.owner.@each.name

    3.4 当CP属性依赖于.property('columns.@each')时:

    • 当columns增加或删除元素。
    • 当columns自身被替换或重新赋值。

    3.5 当CP属性依赖于.property('columns.[]')时:

      与3.4 绑定.property('columns.@each') 行为相同。

    3.6 当通过set方法设置CP属性时,然后调用get方法获取CP属性,则不调用CP回调,set时值被缓存。(CP属性被覆盖)

    3.7 当存在两个互相依赖的CP属性时,仅仅发生三次属性变更。

    3.8 原则上不要将CP的依赖属性附着在另一个CP属性上。

    3.9 当CP属性依赖于对象列表时,例如.property('a.b.c.d')上时,节点上任意对象发生变化时,均会重新计算属性。(链式依赖

    4. CP宏定义

    Ember.computed.empty: empty(属性名)返回bool

    Ember.computed.not: not(属性名)返回bool

    Ember.computed.alias:alias(属性名),双向绑定, alias不要依赖于一个CP.

    Ember.computed.defaultTo: 如果CP属性为null,则读取依赖属性值一次

    Ember.computed.match(属性名, 匹配字符串)

    Ember.computed.gt(属性名,数字)大于返回bool

    Ember.computed.gte(属性名,数字)大于或等于bool

    Ember.computed.and(属性名,属性名) 并集

    Ember.computed.or(属性名, 属性名) 交集

    Ember.computed.collect( 数组 ) 匹配所有项,没有相则为null

    Ember.computed.oneWay(属性名) 单方向从到PC属性. CP可以被设置,但不会影响到CP依赖的属性。

    Ember.computed.readOnly(属性名) CP属性不允许被设置,但CP所依赖的源属性更新CP值。

     更多宏定义请参考这里:http://emberjs.com/api/classes/Ember.computed.html#method_alias

    5. CP使用场景

    5.1 在我们使用的对象上,希望使用一个属性值监听一个或多个属性的变更,或者CP属性强依赖于某些属性,而且还能缓存CP属性值,减少性能损耗。(CP特性请参考3.1)

    5.2 CP可以依赖在一个对象的多个属性上, 特别是绑定在集合元素上甚至监听集合元素内部某一属性,但层次有限制。例如.property('person{name,age}')或.property('pencilBox.[]', penBox.@each.color', penBox.@each)。(CP特性请参考3.2、3.3、3.4)

    5.3 Ember.computed.alias作用于两个强关联对象的双向绑定,并提供缓存机制。

    5.4 通过CP来组合属性,CP属性回调中不能有边界效应等循环、异步方法。

    6. Q & A

    6.1 当计算属性(CP)设置为getter和setter时,其CP回调函数触发的场景:

    • 设置(set)CP属性时,无论何时都触发CP回调方法。
    • 当获取CP属性时,若CP依赖属性未发生变化,则不执行CP回调方法。

    6.2 Ember.Computed(function(){}).property('xxxx') 与 function(){}.property('xxxx')区别:

    • 前者可以用{get:function(){}, set: function(key, newName){}}的方式,不必在判断Argument.length,实现了get、set的语法糖。
      fullName: Ember.computed("firstName", "lastName", {
        get: function() {
          return this.get("firstName") + " " + this.get("lastName");
        },
        set: function(key, newName) {
          var parts = newName.split(" ");
          this.setProperties({ firstName: parts[0], lastName: parts[1] });
          return newName;
        }
      });

     

    6.3 CP之间的依赖行为(cp1->cp2->x):

    • cp2重新计算后,并不会主动触发cp1计算。
    • 如果x更新后,直接获取cp1属性,则cp2也被触发计算。

    6.4 Person.get('firstName')和Person.firstName之间的区别:

      当firstName为(非计算属性)普通属性时,行为相同。

      当firstName为CP属性时,前者能触发CP回调方法,后者不能。

    7. 示例代码

    [github示例代码](https://github.com/Cuiyansong/ember-table-learnning/tree/master/ember-test/tests/unit)

    Ember更新日志:http://emberjs.com/deprecations/v1.x/#toc_deprecate-using-the-same-function-as-getter-and-setter-in-computed-properties 

    Ember-Data: http://guides.emberjs.com/v1.13.0/object-model/computed-properties-and-aggregate-data/

  • 相关阅读:
    VS2013编写的C#程序,在xp下会报错说“不是合法的win32程序”。
    能根据串口驱动来 确定com号
    javaweb工程,Servlet里面获取当前WEB跟路径的文件绝对路径地址
    import了sun开头的类,虽然它在代码里压根就没派上用处!但是必须得引用!
    页面关闭时触发的时间
    jquery设置元素的readonly和disabled
    ibatis CDATA
    form的submit与onsubmit的用法与区别
    C#操作AD及Exchange Server总结(一)
    AD如何用C#进行增删改、查询用户与OU
  • 原文地址:https://www.cnblogs.com/cuiyansong/p/4550150.html
Copyright © 2011-2022 走看看