dom-repeat过滤/排序重绘错误

时间:2016-10-27 15:01:23

标签: polymer web-component

dom-repeat重绘方式存在问题。下面的代码段演示了对简单对象数组进行过滤和排序可能会错误地向最终用户显示数据。

我已经确定这与_applyFullRefresh方法(https://github.com/Polymer/polymer/blob/master/src/lib/template/dom-repeat.html#L482)中的实例重用有关。

我能够通过重复使用匹配键的实例来修改此方法以创建工作解决方案。这里可以看到差异:https://github.com/Polymer/polymer/compare/master...TomK:patch-1

我的问题:这是dom-repeat的补丁,这是我实现工作范例的唯一方法吗?

代码段预期结果 选择过滤/排序的任意组合后,一行(item contentx-item content)上的两个数字应始终相同。



<!DOCTYPE html>
<html>
  <head>
    <meta name="description" content="basic polymer jsbin">
    <meta charset="utf-8">
    <base href="//polygit.org/components/">
    <script src="webcomponentsjs/webcomponents-lite.js"></script>
    <link rel="import" href="polymer/polymer.html">

    
  <dom-module id="x-item-test">
    <template>
      x-item content: [[_innerText]]
    </template>
    <script>
      HTMLImports.whenReady(
        function ()
        {
          Polymer(
            {
              is:           'x-item-test',
              properties:   {
                _innerText: {type: String}
              },
              attached:     function ()
                            {
                              Polymer.RenderStatus.afterNextRender(this, this.__updateProp.bind(this));
                              new MutationObserver(this.__updateProp.bind(this))
                                .observe(this, {childList: true, subtree: true, characterData: true});
                            },
              __updateProp: function ()
                            {
                              var nodes = this.getEffectiveChildNodes(), output = '';
                              for(var i in nodes)
                              {
                                var n = nodes[i];
                                if(n.nodeType == 3 && n.nodeValue)
                                {
                                  output += n.nodeValue;
                                }
                              }
                              this._innerText = output;
                            }
            }
          );
        }
      );
    </script>
  </dom-module>

  <dom-module id="test-app">
    <template>
      <div>
        Filter <input type="checkbox" checked="{{_applyFilter::change}}">
      </div>
      <div>
        Sort <input type="checkbox" checked="{{_reverse::change}}">
      </div>
      <template is="dom-repeat" items="[[actions]]" filter="{{_filter(_applyFilter)}}" sort="{{_sort(_reverse)}}">
        <div>Item content: [[item.id]] -
          <x-item-test>[[item.id]]
            <div>ignored</div>
          </x-item-test>
        </div>
      </template>
    </template>
    <script>
      HTMLImports.whenReady(
        function ()
        {
          Polymer(
            {
              is:         'test-app',
              properties: {
                actions:      {
                  type:  Array,
                  value: [{id: '1', primary: true}, {id: '2'}, {id: '3', primary: true}, {id: '4'}]
                },
                _applyFilter: {type: Boolean, value: false},
                _reverse:     {type: Boolean, value: false}
              },
              _filter:    function (applyFilter)
                          {
                            return function (item)
                            {
                              return !applyFilter || item.primary;
                            }
                          },
              _sort:      function (reverse)
                          {
                            return function (a, b)
                            {
                              if(reverse)
                              {
                                return a.id < b.id
                              }
                              return a.id >= b.id;
                            }
                          }
            }
          );
        }
      );
    </script>
  </dom-module>

</head>
<body>
<test-app></test-app>
</body>
</html>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

在Polymer 1.x中,由于dom-repeat重用实例的方式,我认为没有一种好方法可以做你想做的事。

执行属性绑定而不是将轻型DOM子项传递给x-item-test将是在1.x中执行此操作的最佳方法。

对每个数组项执行实例查找是O(n ^ 2)我认为这对于一般情况是不可接受的。

如果由于某种原因你确实需要使用轻型DOM子,那么我能想到的最后一个(相当可怕的)选项就是拥有一个dom-change监听器来遍历模板实例并调用它们的一些更新方法。

我无法想象任何一个用于物业绑定的用例,但有时我不是很有想象力。

我没有在2.0预览中看到这个问题:

http://jsbin.com/vuritog/2/edit?html,output

希望有所帮助。