Polymer 聚合dom重复不以功能作为项渲染更改

Polymer 聚合dom重复不以功能作为项渲染更改,polymer,polymer-1.0,Polymer,Polymer 1.0,在Polymer中,我使用一个函数来计算dom repeat的项: <template is="dom-repeat" items="[[first4People(people, people.*)]]"> <div> First: <span>[[item.first]]</span> Last: <span>[[item.last]]</span> </div> </templa

在Polymer中,我使用一个函数来计算
dom repeat
的项:

<template is="dom-repeat" items="[[first4People(people, people.*)]]">
  <div>
    First: <span>[[item.first]]</span>
    Last: <span>[[item.last]]</span>
  </div>
</template>
  <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:

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

  <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>
// 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);
});

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

  <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>
// 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);
});

以下是正确的解决方案:

  <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>
错误之处在于:

  <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>

  <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>

索引:[[Index]]

首先是这样:[[arrayItem(people.*,index,'First')]]
首先不是这样:[[item.First]]

西米拉:

  <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>

  <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>

以下是正确的解决方案:

  <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>
错误之处在于:

  <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>

  <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>

索引:[[Index]]

首先是这样:[[arrayItem(people.*,index,'First')]]
首先不是这样:[[item.First]]

西米拉:

  <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>

  <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>

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

  <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>
而且
dom repeat
不知道对
people.0.first
的更改与它的
items
属性相关,因此它也不会以这种方式获得更改

  <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>
修复它以替换
people.0
对象,如下所示:

  <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>
renameFirstPerson: function() {
  // create a new object to defeat dirty-check.
  var updated = Object.assign({}, this.people[0]);
  updated.first = updated.first + 'Foo';
  // swap the new object in with 'set', so the observer gets called. 
  this.set('people.0', updated);
}

这里还有一些其他的方法,但是没有一种是非常简单的。希望这能有所帮助。

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

  <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>
而且
dom repeat
不知道对
people.0.first
的更改与它的
items
属性相关,因此它也不会以这种方式获得更改

  <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>
修复它以替换
people.0
对象,如下所示:

  <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>
renameFirstPerson: function() {
  // create a new object to defeat dirty-check.
  var updated = Object.assign({}, this.people[0]);
  updated.first = updated.first + 'Foo';
  // swap the new object in with 'set', so the observer gets called. 
  this.set('people.0', updated);
}

这里还有一些其他的方法,但是没有一种是非常简单的。希望这能有所帮助。

虽然这确实解决了问题,但我认为这是偶然的,因为
arrayItem(people.*,index,'first')
取决于整个
人员
列表。据我所知,我并没有显式绑定到数组项。(例如,我从不写
people.0.first
people[0]。first
)。是的<代码>项。首先在
dom repeat
中完全有效-以这种方式访问数组项正是
dom repeat
的设计目的。这就解决了问题,因为
arrayItem()
将在每次
people.*
更改时重新评估,这并不是非常有效。虽然这确实解决了问题,但我认为它会顺便解决问题,因为
arrayItem(people.*,index,'first')
取决于整个
people
列表。据我所知,我并没有显式绑定到数组项。(例如,我从不写
people.0.first
people[0]。first
)。是的<代码>项。首先在
dom repeat
中完全有效-以这种方式访问数组项正是
dom repeat
的设计目的。这解决了问题,因为每当
人员发生更改时,
arrayItem()
都将重新评估。*
这不是非常有效的。感谢您的修复!令人遗憾的是,requestAnimationFrame是必需的:(至少在2.0中,它将以更易于理解的方式工作。感谢修复!令人遗憾的是,requestAnimationFrame是必需的:(至少在2.0中,它将以更易于理解的方式工作)。
  <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>