Как правильно распространять изменения от одного LitElement к дочернему LitElement? - PullRequest
0 голосов
/ 12 сентября 2018

У меня есть LitElement, который представляет загрузку файлов для нескольких файлов. При этом используется подкомпонент, представляющий каждый файл.

Я изо всех сил пытаюсь найти примеры наилучшей практики для распространения изменений в подкомпоненте, используя LitElements, так как он очень отличается от Polymer 3

Вот сокращенный пример того, что я пытаюсь:

import './uploadFile.js';
class Upload extends LitElement {
  ...
  static get properties() { return { files: Object } }
  _render({files}) {
    return html`
      <input type="file" multiple onchange="...">
      ${this.renderFiles(files)}`
  }
  renderFiles(files) {
    const filesTemplate = [];                                                                                        
    for (var i = 0; i < files.length; i++) {                                                                         
      filesTemplate.push(html`
        <upload-file file="${files[i]}"></upload-file>
       `);                                
    }                                                                                                                
    return filesTemplate;                                                                                            
  }
}

Когда я обновляю статус файла, компонент выгрузки воспроизводится повторно, а компонент загрузки файла - нет.

Что я здесь не так делаю? Нет примеров использования LitElement.

1012 * ТИА *

1 Ответ

0 голосов
/ 13 сентября 2018

Лучшая практика - «свойства вниз, события вверх»; Это означает, что родительские элементы должны обмениваться данными с дочерними элементами, привязывая к ним свойства, а дочерние элементы должны обмениваться данными с родителями, вызывая событие с соответствующими данными в деталях события.

Я не могу комментировать то, что вы делаете неправильно, поскольку я не вижу, как вы обновляете статус файлов или вашу реализацию дочернего элемента.

Следует помнить одну вещь: из-за грязной проверки lit-element может наблюдать только изменения свойств верхнего уровня, которые вы перечислили в геттере properties, а не их под-свойства.

Что-то вроде

this.myObj = Object.assign({}, this.myObj, {thing: 'stuff'});

будет вызывать изменения объекта и его под-свойств для отображения, в то время как

this.myObj.thing='stuff';

не будет.

Чтобы изменения под-свойства вызывали повторную визуализацию, вам нужно либо запросить ее с помощью requestRender(), либо клонировать весь объект.

Вот пример кода, показывающего базовую модель «свойства вниз, события вверх»:

Предупреждение: горит элемент все еще в предварительной версии, и синтаксис изменится.

родитель-element.js

import { LitElement, html} from '@polymer/lit-element';
import './child-element.js';

class ParentElement extends LitElement {
  static get properties(){
    return {
      myArray: Array
    };
  }
  constructor(){
    super();
    this.myArray = [ 
      { val: 0, done: false },
      { val: 1, done: false },
      { val: 2, done: false },
      { val: 3, done: false }
    ];
  }
  _render({myArray}){
    return html`
      ${myArray.map((i, index) => { 
        return html`
          <child-element 
            on-did-thing="${(e) => this.childDidThing(index, i.val)}" 
            val="${i.val}"
            done="${i.done}">
          </child-element>
      `})}
    `;
  }

  childDidThing(index, val){
    this.myArray[index].done=true;
    /**
     * Mutating a complex property (i.e changing one of its items or
     * sub-properties) does not trigger a re-render, so we must
     * request one:
     */
    this.requestRender();

    /**
     * Alternative way to update a complex property and make
     * sure lit-element observes the change is to make sure you 
     * never mutate (change sub-properties of) arrays and objects.
     * Instead, rewrite the whole property using Object.assign.
     * 
     * For an array, this could be (using ES6 object syntax):
     * 
     * this.myArray = 
     * Object.assign([], [...this.myArray], { 
     *   [index]: { val: val, done: true }
     * });
     * 
    */
  }
}
customElements.define('parent-element', ParentElement);

ребенок-element.js

import { LitElement, html} from '@polymer/lit-element';

class ChildElement extends LitElement {
  static get properties(){
    return {
      val: Number,
      done: Boolean
    };
  }
  _render({val, done}){
    return html`
      <div>
        Value: ${val} Done: ${done} 
        <button on-click="${(e) => this.didThing(e)}">do thing</button>
      </div>
    `;
  }
  didThing(e){
    var event = new CustomEvent('did-thing', { detail: { stuff: 'stuff'} });
    this.dispatchEvent(event);
  }
}
customElements.define('child-element', ChildElement);

Надеюсь, это поможет.

...