聚合物dom-repeat不会使用函数作为项目进行更改

时间:2016-12-01 01:34:21

标签: polymer polymer-1.0

在聚合物中,我使用函数来计算dom-repeat

的项目
<template is="dom-repeat" items="[[first4People(people, people.*)]]">
  <div>
    First: <span>[[item.first]]</span>
    Last: <span>[[item.last]]</span>
  </div>
</template>

但无论我尝试什么,当我更改people的子属性(例如people.0.first)时,我无法让它呈现更新。对数组本身的更改有效(例如this.push('people', ...))。我很可能被dirty check击中,在这种情况下,我无法弄清楚如何覆盖它。

完整示例:                                           

  <body fullbleed unresolved>

    <widget-example></widget-example>

    <dom-module id="widget-example">
        <template>
          <div style="color: red;">Why doesn't rename first person cause a visible change?</div>
          <div>First 4 people:
            <template is="dom-repeat" items="[[first4People(people, people.*)]]">
              <div>
              First: <span>[[item.first]]</span>
              Last: <span>[[item.last]]</span>
              </div>
            </template>
          </div>

          <div>
            <!-- Why doesn't this work? -->
            <button on-tap="renameFirstPerson">Rename first person</button>
            <button on-tap="sendFrontToBack">Send front to back</button>
          </div>
        </template>
        <script>
        Polymer({
            is: "widget-example",
            properties: {
                people: {
                    type: Array,
                    value: () => [
                      {'first': 'Joe', 'last': 'Blogs'}, 
                      {'first': 'Jon', 'last': 'Bigs'}, 
                      {'first': 'John', 'last': 'Doe'}, 
                      {'first': 'Josh', 'last': 'Blo'},
                    ],
                },
            },

            observers: [
              'o(people.*)',
            ],

            o: function(change) {
              console.log('o', change)
            },

            first4People: function() {
              console.log('first4People called');
              return this.people.slice(0, 4);
            },

            renameFirstPerson: function() {
              console.log('before sendFrontToBack', this.people)
              this.set(['people.0.first'], this.people[0].first+'Foo');

            // None of this causes the rename to show up.
              var person = this.people[0];
              this.people[0] = {};
              this.people[0] = person;
              this.notifyPath('people.0');

              this.set('person', {});
              this.set('person', person);

              var people = this.get('people');
              this.set('people', []);
              this.set('people', people);
            },

            sendFrontToBack: function() {
              console.log('before sendFrontToBack', this.people)
              var last = this.shift('people', this.people);
              this.push('people', last);
              console.log('after sendFrontToBack', this.people)
            },
        });
      </script>
    </dom-module>
  </body>
</html>

Plunker:http://plnkr.co/edit/Yv27I053bk4e3cFbFuhK?p=preview

3 个答案:

答案 0 :(得分:3)

此处的具体问题涉及使用计算绑定为items属性创建匿名数组。使用set更改子属性时,会重新计算计算出的绑定,但people.0 对象没有更改,因此当dom-repeat迭代时数组,脏检查告诉它对象没有改变。

dom-repeat并不知道对people.0.first的更改与其items属性相关,因此它无法以此方式进行更改,或者

一个修复它来替换{​​{1}}对象,如下所示:

people.0

您可以在这里采取其他一些方法,但这些方法都不是非常简单。希望这会有所帮助。

答案 1 :(得分:2)

Polymer 1.x这种工作方式很奇怪,在2.0中应该工作得更好但是现在你必须清空然后重写整个数据数组来重新评估变化。出于某种原因,如果你这样做仍然没有发生任何事情,但如果你在一个新的框架中给出新值,那么它开始工作:

// Save the data locally
let peoples = this.people;

// Do the change in the local array
peoples[0].first += 'Foo';

// Empty the data so it can reevaluate 
this.people = []; // this.set('people', []);

// Insert the new data in a new frame     
requestAnimationFrame(time => {
    this.people = peoples; // this.set('people', peoples);
});

http://plnkr.co/edit/cLirT95ot1d5BMFWItwD?p=preview

答案 2 :(得分:1)

这是正确的解决方案:Plunk

错误的是:

  

Explicit bindings to array items by index isn’t supported

<template is="dom-repeat" items="[[first4People(people, people.*)]]"> 
    <div>
        Index: <span>[[index]]</span>
        <br>
        First as this:[[arrayItem(people.*, index, 'first')]]
        <br>
        First not as this: <span>[[item.first]]</span>
   </div>
   <br><br>
</template>

Simmilar:

cannot changed the property of an object inside an array

Polymer, binding to array items not working