2014-09-24 32 views
0

我有一个对象数组的模型。这些对象有一个用户可以更新的属性。是否有一种习惯用法来计算聚合物中数组元素的子集?

在UI的另一部分中,我想展示一些有关数组的统计信息;项目的总数量和具有该属性设置的项目的数量。

一个数组代替对象的例子。点击列表项切换“一”属性:http://jsfiddle.net/rskqbquL/4/

<polymer-element name="test-cool"> 
    <template> 
     <ol> 
      <template repeat="{{item, i in list}}"> 
       <li on-tap="{{onTap}}" x-index="{{i}}">{{item[0]}}</li> 
      </template> 
     </ol> 
     <p>Total: {{list.length}}</p> 
     <p>A:s: {{list | countA}}</p> 
    </template> 
    <script> 
     Polymer("test-cool", { 
      list: [["a"], ["ab"], ["ac"], ["d"], ["e"]], 

      countA: function(list) { 
       var ret = 0; 

       list.forEach(function(item) { 
        if (item[0].indexOf("a") >= 0) ++ret; 
       }); 
       return ret; 
      }, 
      onTap: function(e, _, el) { 
       var item = el.innerText; 
       var index = parseInt(el.getAttribute("x-index")); 

       if (item.indexOf("a") >= 0) { 
        this.list[index][0] = item.slice(1); 
       } else { 
        this.list[index][0] = "a" + item; 
       } 

       // Workaround 
       this.list = this.list.slice(); 
      } 
     }); 
    </script> 
</polymer-element> 

<test-cool></test-cool> 

我无法找到任何方式来观察一个数组的所有项目)的特定属性,列表中的onTap因此解决方法虚拟分配(。

什么是收集有关数组子集的统计数据的惯用聚合物方式?

回答

0

使用过滤器和发痒的list(例如1this.list = this.list.slice()) works, but every time the上抽头handlers gets called, the entire DOM list is rendered. Instead, I would create a counterA`变量来跟踪该阵列的长度

此外,代替使用。:

var item = el.innerText; 
var index = parseInt(el.getAttribute("x-index")); 

你可以直接使用的数据模型(docs):

var item = el.templateInstance.model.item; 
var index = el.templateInstance.model.i; 

一种方法来环节T他是一样的东西http://jsbin.com/fitav/1/edit

<p>A:s: {{countA}}</p> 

onTap: function(e, detail, el) { 
    var item = el.templateInstance.model.item; 
    var index = el.templateInstance.model.i; 

    this.list[index][0] = this.hasA(item[0]) ? 
          item[0].slice(1) : "a" + item; 

    this.countA = this.filterA(); 
}, 
hasA: function(item) { 
    return item.indexOf("a") >= 0; 
}, 
listChanged: function() { 
    this.countA = this.filterA(); 
} 
0

目前最好的做法是使用观察踢触发重新计算。 Fwiw,我们通常对这个答案不满意,并且正在努力实现更好的自动化。

的开局是描述你的绑定像这样:

<p>A:s: {{list | countA(kick)}}</p> 

,并在其中的列表项被更改的关键地方,递增kick财产。要清楚,kick属性除了触发重新计算之外没有其他用途。

kick: 0, 
    onTap: function(e) { 
     var item = e.target.templateInstance.model.item; 
     item[0] = this.toggleA(item[0]); 
     this.kick++; 
    } 

正如我说,这是一个暂时的解决方案,直到我们计算出更自动化的变化检测或至少可观看提供的API。

全面落实这里:http://jsbin.com/naboke/5/edit

0

下面是使用我最近写了用于此目的的聚合物元件的解决方案:<observe-array-items><observe-array-items>简化了为阵列中的每个项目创建/维护PathObserver的过程。

<script src="//www.polymer-project.org/platform.js"></script> 
 
<link rel="import" href="//www.polymer-project.org/components/polymer/polymer.html"> 
 
<link rel="import" href="//rawgit.com/jeffposnick/observe-array-items/master/observe-array-items.html"> 
 

 
<polymer-element name="array-observation"> 
 
    <template> 
 
    <observe-array-items array="{{list}}" 
 
       path="text" 
 
       on-array-item-changed="{{handleArrayItemChanged}}"> 
 
    </observe-array-items> 
 
    
 
    <ol> 
 
     <template repeat="{{item in list}}"> 
 
     <li on-tap="{{handleListTap}}">{{item.text}}</li> 
 
     </template> 
 
    </ol> 
 
    
 
    <p> 
 
     <input type="text" value="{{newItemText}}"> 
 
     <button on-tap="{{handleAddItem}}">Add Item</button> 
 
    </p> 
 

 
    <p>Total: {{list.length}}</p> 
 
    <p>'A's: {{countOfA}}</p> 
 
    </template> 
 

 
    <script> 
 
    Polymer({ 
 
     countOfA: 0, 
 
     list: null, 
 
     newItemText: 'f', 
 
     
 
     listChanged: function() { 
 
     // This will be triggered when list is first initialized, 
 
     // and any time an item is added or removed from the array. 
 
     var count = 0; 
 
     
 
     this.list.forEach(function(item) { 
 
      if (this._hasA(item.text)) { 
 
      count++; 
 
      } 
 
     }.bind(this)); 
 
     
 
     this.countOfA = count; 
 
     }, 
 
     
 
     _hasA: function(str) { 
 
     console.log('checking', str); 
 
     return str.indexOf('a') >= 0; 
 
     }, 
 
     
 
     handleArrayItemChanged: function(e) { 
 
     if (!this._hasA(e.detail.oldValue) && this._hasA(e.detail.newValue)) { 
 
      // If the old value didn't have an 'a' and the new value does, then increment countOfA. 
 
      this.countOfA++; 
 
     } else if(this._hasA(e.detail.oldValue) && !this._hasA(e.detail.newValue)) { 
 
      // If the old value did have an 'a' and the new value doesn't, then decrement countOfA. 
 
      this.countOfA--; 
 
     } 
 
     // Don't do anything for the other cases, since 'a'-ness has stayed the same. 
 
     }, 
 

 
     handleListTap: function(e, _, el) { 
 
     var item = el.templateInstance.model.item; 
 

 
     if (this._hasA(item.text)) { 
 
      item.text = item.text.slice(1); 
 
     } else { 
 
      item.text = 'a' + item.text; 
 
     } 
 
     }, 
 
     
 
     handleAddItem: function() { 
 
     this.list.push({text: this.newItemText}); 
 
     }, 
 

 
     ready: function() { 
 
     this.list = [ 
 
      {text: 'a'}, 
 
      {text: 'ab'}, 
 
      {text: 'ac'}, 
 
      {text: 'd'}, 
 
      {text: 'e'} 
 
     ]; 
 
     } 
 
    }); 
 
    </script> 
 
</polymer-element> 
 

 
<h1>Polymer Demo: Observing Changes to Properties of Items in an Array</h1> 
 
<array-observation></array-observation>

我认为这是解决你想要做什么,因为它在很大程度上依赖于观察回调确保相关的状态保持最新的一个相当习惯的方法。您可以直接在代码中的任何位置修改数据,而无需担心忘记调用特定的帮助函数等。

相关问题