Polymer 1.5如何在使用不可变数据结构时通知dom-repeat

时间:2016-06-23 14:07:08

标签: polymer polymer-1.0

问题:我们在应用中使用redux来管理状态。这导致渲染问题。 dom-repeater未正确处理数组中的更改(f.e.remove)。发生的事情是数据和标记模板混在一起。

我想找到一种方法来通知dom-repeat元素有关数组更改的信息。

<template is="dom-repeat" items="[[data.items]]">
    <repeater-item config="[[item]]" on-change="_onChange"></repeater-item>
</template>

我的Polymer应用程序中有不可变状态,所以我不能使用Polymer数组变异方法。

here is a plnkr

我尝试了什么:
1)this.set('data', newState);
因此,如果我将删除数据数组中的第一项&#39; dom-repeat&#39;将删除最后一个模板<repeater-item>,并将重新分配这样的数据:

template-1 receives data 2,
template-2 receives data 3,
...

2)第二次尝试我试图通知Splices:

var splices = Polymer.ArraySplice.calculateSplices(newState.items, this.data.items);
this.data = newState;
this.notifySplices('data.items', splices);

结果相同

3)由于某种原因,以下几乎可以工作..

var splices = Polymer.ArraySplice.calculateSplices(newState.items, this.data.items);
this.data.items = newState.items;
this.notifySplices('data.items', splices);

这导致正确的模板删除,但在这里我收到一个错误:

VM47184 polymer-mini.html:2046 Uncaught TypeError: Cannot read property 'length' of undefined

通知&dom-repeat&#39;的正确方法是什么?如果使用不可变状态?

1 个答案:

答案 0 :(得分:1)

我已经能够阻止选项3的错误;为新数组添加Polymer.Collection.get似乎可以防止在方法完成和dom-repeat呈现更改后发生的错误。

_remove(id) {
  var newState = {
    items: this.data.items.filter(item => item.id !== id)
  };

  // Polymer.Collection.get somehow prevents an exception _after_ notifySplices is called
  Polymer.Collection.get(newState.items);

  // Retro-actively calculate splices in Polymer fashion
  var prev = (this.data.items || []);
  var splices = Polymer.ArraySplice.calculateSplices(newState.items, prev);

  // Change the data _without_ Polymer being aware of it (because it isn't a direct property of the element)
  this.data.items = newState.items;

  // Notify Polymer about the array changes so dom-repeat can re-use the correct templates
  this.notifySplices('data.items', splices);
}

查看实际操作:http://plnkr.co/edit/fFGWfL?p=preview

我不知道为什么这可以防止异常,更多的是偶然的发现。

但这似乎仍然是一个次优解决方案,因为你必须在一个包装器对象中隐藏受影响的数组。