2014-05-17 42 views
1

我有一个数组,我想显示前N个元素。这个数组发生了变化,并且保存在我的应用中的另一个组件中。聚合物:变化不总是通过过滤器

我看到一个错误,但如果我显示所有的数组元素,一切都很好。如果我通过获取.slice()的数组副本并将其放入另一个字段并显示为前N个元素过滤的字段来响应我的数组更改,那么一切都很好。但是,如果我只显示通过前N个元素过滤的原始数组,那么DOM从不更新为更改。

下面是展示了这个问题的bug的codepen减少:http://codepen.io/rictic/pen/ienJK?editors=101

全码:

<script src="http://www.polymer-project.org/platform.js"></script><script src="http://www.polymer-project.org/components/web-animations-js/web-animations.js"></script><link rel="import" href="http://www.polymer-project.org/components/polymer/polymer.html"> 
<my-app></my-app> 
<script>console.clear()</script> 


<polymer-element name='my-app'> 
    <template> 
    <template if='{{results}}'> 
     r in results 
     <ul> 
     <template repeat='{{ r in results }}'> 
      <li>{{r.value}} - {{r.name}}</li> 
     </template> 
     </ul> 

     r in processedResults | first(5) 
     <ul> 
     <template repeat='{{ r in processedResults | first(5) }}'> 
      <li>{{r.value}} - {{r.name}}</li> 
     </template> 
     </ul> 

     r in results | first(5) 
     <ul> 
     <template repeat='{{ r in results | first(5) }}'> 
      <li>{{r.value}} - {{r.name}}</li> 
     </template> 
     </ul> 

    </template> 
    </template> 
    <script> 
    </script> 
</polymer-element> 

<script> 
'use strict'; 

var names = ['Alice', 'Bob', 'Charline', 'Daryl', 'Elise', 'Franz', 'Geraldine', 'Happsburg', 'Irene', 'Jerome']; 

Polymer('my-app', { 
    results: [{value: 10, name: 'root'}], 
    first: function(a, k) { 
    // A filterer to display the first k elements of an array. 
    if (!a) { 
     return a; 
    } 
    return a.slice(0, k); 
    }, 
    domReady: function() { 
    // Populate the results array. 
    for (var i = 0; i < 10; i++) { 
     this.results.push({value: i, name: names[i]}); 
    } 

    // Once a second, mutate and sort the array 
    setInterval(function() { 
     var randomChoice = Math.round(Math.random() * (this.results.length - 1)); 
     this.results[randomChoice].value *= 2; 
     this.results.sort(function(a, b) { 
     if (a.value != b.value) { 
      return b.value - a.value; 
     } 
     return a.name.localeCompare(b.name); 
     }); 
    }.bind(this), 1000); 
    }, 
    resultsChanged: function() { 
    // Copy this.results into this.processedResults. 
    this.processedResults = this.results.slice(); 
    } 
}); 
</script> 
+0

尝试初始化'results'准备就绪。如果属性是数组/对象,那么它们应该在那里初始化。 – user568109

+0

我可以使[此](http://codepen.io/anon/pen/Ctzhl?editors=101)工作。但是,似乎是一个错误。除非完全修改,否则它不会观察对象属性的更改。 – user568109

+0

关于初始化'结果'准备就绪的好处。在我的真实应用程序中,有另一个元素从服务器响应中获取JSON.parse的“结果”,然后在将结果赋予与上面的“my-app”相对应的元素后,它继续变更相同的数组使用'.push'和'.sort'。应用程序的行为仍然是上述错误。如果我有更多的时间,我想我可以逐步浏览代码,看看结果在哪里被观察到,以及在每种情况下的结果如何不同,这真的很有趣。 –

回答

1

我相信你可以在created回调,一切设置的结果会工作。这里是an example CodePencreated回调是本地自定义元素的一部分,并在ready(由Polymer添加以知道何时设置了各种功能(如数据绑定)并准备好摇摆)时执行。我仍然不清楚为什么你必须这样做,所以我已经要求团队成员向我解释它,当我知道更多时,我会留下另一条评论:)

编辑

在与聚合物表达式的作者之一交谈之后,听起来你的原始代码应该已经工作了,但是如果对象model.results指向变异,过滤器当前不会再运行。相反,如果路径指向model.results指向更改的对象,它们只会重新运行。这看起来像是过滤器的一个缺点,我们正在研究改变行为,以便它可以像您期望的那样工作。

+0

啊,我应该考虑在聚合物表达式上寻找现存的问题。看起来像其他人已经从https://github.com/Polymer/polymer-expressions/issues/28和https://github.com/Polymer/polymer-expressions/pull/23发表评论。我已经订阅了这些问题,谢谢! –

+0

具体而言,'created'和'ready'之间的区别在于'created'被称为_before_标记中设置的属性值被转换为属性值。如果你有一个属性是一个对象或数组,你应该在'created'中设置默认值,当它将属性值(字符串)转换为JavaScript对象时,它会为Polymer提供一个类型提示。 'ready'回调在属性初始化后被调用,所以你可以在脚本中使用这些值。另一方面,在'ready'回调中设置属性值将覆盖标记中设置的任何值。 – DocDude