Как уведомить мутацию массива к родительскому компоненту в полимере 3 - PullRequest
0 голосов
/ 08 февраля 2019

У меня есть 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 голосов
/ 10 февраля 2019

Родительский компонент будет обрабатывать уведомления об изменениях только в двусторонних привязках (с использованием фигурных скобок).При привязке данных неправильно используется односторонняя привязка (квадратные скобки).

<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) не обнаруживает мутации массива.Вы должны использовать комплексный наблюдатель .Вы могли наблюдать изменения данных / длины и / или мутации массива :

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