如何将阵列突变通知聚合物3中的母体组分

时间:2019-02-08 19:27:59

标签: javascript arrays polymer observers polymer-3.x

例如,我有2个使用相同数组绑定的组件:

{
 title: "food",
 data : ["data1", "data2", "data3"]
}

标题位于父组件上,并且数据从父组件绑定到子组件,并与数组的子作品绑定。

当我删除数组数据元素通知父组件时该怎么办?

这里是例子。

在示例中,我有一个具有绑定数组的子级,以及一种删除数组元素并进行通知的方法。父组件有一个名为arrayChanges的观察者。

如果代码有效,则父组件必须知道子数组的长度,但是无效。

<script type='module'>
  import {PolymerElement, html} from 'https://unpkg.com/@polymer/polymer/polymer-element.js?module';
  import {} from 'https://unpkg.com/@polymer/polymer@3.1.0/lib/elements/dom-repeat.js?module';

  class ParentComp extends PolymerElement {
    static get properties() {
      return {
        myArr: {
          type: Array,
          observer: "arrayChanges"
        },
        changes: {
          type: String
        }
      };
    }
    static get template() {
      return html`
        <div>[[myArr.title]]</div>
        <children-comp data='[[myArr.data]]'></children-comp>
        <div>[[changes]]</div>
      `;
    }
    ready(){
      super.ready();
      this.myArr = {
        title : "My component",
        data : [
          {titulo: "titulo1", comment : "im comment number 1"},
          {titulo: "titulo2", comment : "im comment number 2"}
        ]
      }
    }
    arrayChanges(){
      this.changes = "Array length : "+this.myArr.data.length;
      console.log("the Array has been changed");

    }

  }

  class ChildrenComp extends PolymerElement {
    static get properties() {
      return {
        data: {
          type: Array,
          notify: true
        }
      };
    }
    static get template() {
      return html`
      <ul>
        <dom-repeat items='[[data]]' >
          <template>
            <li>
              [[index]] )
              [[item.titulo]]
              [[item.comment]]
              <button data-index$='[[index]]' on-click='handle_button'>Borrar</button>
              <hr>            
            </li>
          </template>
        </dom-repeat>
      </ul>      
      `;
    }
    handle_button(e){
      var index = e.currentTarget.dataset.index;
      this.notifyPath("data");
      this.splice("data", index, 1);
    }


  }
  customElements.define('children-comp', ChildrenComp);
  customElements.define('parent-comp', ParentComp);


</script>
<parent-comp></parent-comp>

1 个答案:

答案 0 :(得分:3)

父组件将仅处理two-way bindings中的更改通知(使用大括号)。您的数据绑定错误地使用了单向绑定(方括号)。

<children-comp data='[[myArr.data]]'></children-comp>
                     ^^          ^^ square brackets: one-way binding
<children-comp data='{{myArr.data}}'></children-comp>
                     ^^          ^^ curly brackets: two-way binding

还要注意,简单的观察者(在myArr-property声明中指定)不会检测到数组突变。您应该改用complex observer。您可以观察到数据/长度的变化和/或array mutations

static get properties() {
  return {
    myArr: {
      // type: Array, // DON'T DO THIS (myArr is actually an object)
      type: Object,
      // observer: 'arrayChanges'  // DON'T DO THIS (doesn't detect array splices)
    }
  }
}

static get observers() {
  return [
    'arrayChanges(myArr.data, myArr.data.length)',  // observe data/length changes
    'arraySplices(myArr.data.splices)',             // observe array mutations
  ]
}

arrayChanges(myArrData, myArrDataLength) {
  console.log({
    myArrData,
    myArrDataLength
  })
}

arraySplices(change) {
  if (change) {
    for (const s of change.indexSplices) {
      console.log({
        sliceIndex: s.index,
        removedItems: s.removed,
        addedItems: s.addedCount && s.object.slice(s.index, s.index + s.addedCount)
      })
    }
  }
}

<html>
<head>
  <script src="https://unpkg.com/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
</head>
<body>
  <script type='module'>
  import {PolymerElement, html} from 'https://unpkg.com/@polymer/polymer/polymer-element.js?module';
  import {} from 'https://unpkg.com/@polymer/polymer@3.1.0/lib/elements/dom-repeat.js?module';

  class ParentComp extends PolymerElement {
    static get properties() {
      return {
        myArr: {
          type: Array,
        },
        changes: {
          type: String
        }
      };
    }

    static get observers() {
      return [
      'arrayChanges(myArr.data, myArr.data.length)',
      'arraySplices(myArr.data.splices)',
      ]
    }

    static get template() {
      return html`
        <div>[[myArr.title]]</div>
        <children-comp data='{{myArr.data}}'></children-comp>
        <div>{{changes}}</div>
      `;
    }
    ready(){
      super.ready();
      this.myArr = {
        title : "My component",
        data : [
          {titulo: "titulo1", comment : "im comment number 1"},
          {titulo: "titulo2", comment : "im comment number 2"}
        ]
      }
    }

    arrayChanges(myArr, myArrLength){
      this.changes = "Array length : " + myArrLength;
      console.log("the Array has been changed", myArr);
    }

    arraySplices(change) {
      if (change) {
        for (const s of change.indexSplices) {
          console.log({
            sliceIndex: s.index,
            removedItems: s.removed,
            addedItems: s.addedCount && s.object.slice(s.index, s.index + s.addedCount)
          })
        }
      }
    }
  }

  class ChildrenComp extends PolymerElement {
    static get properties() {
      return {
        data: {
          type: Array,
          notify: true
        }
      };
    }
    static get template() {
      return html`
      <ul>
        <dom-repeat items='[[data]]' >
          <template>
            <li>
              [[index]] )
              [[item.titulo]]
              [[item.comment]]
              <button data-index$='[[index]]' on-click='handle_button'>Borrar</button>
              <hr>
            </li>
          </template>
        </dom-repeat>
      </ul>
      `;
    }
    handle_button(e){
      var index = e.currentTarget.dataset.index;
      this.notifyPath("data");
      this.splice("data", index, 1);
    }

  }
  customElements.define('children-comp', ChildrenComp);
  customElements.define('parent-comp', ParentComp);
</script>

<parent-comp></parent-comp>

</body>
</html>