我有一个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的示例。
TIA
答案 0 :(得分:5)
最佳做法是“减少财产,增加事件”;意思是父元素应该通过与孩子绑定属性来与孩子共享数据,子元素应该通过引发带有事件详细信息的事件来与父母共享数据。
我无法评论您在做什么,因为我看不到您如何更新文件的状态或子元素的实现。
要知道的一件事是,由于脏检查,lit-element只能观察到您在properties
getter中列出的顶级属性的更改,而不能观察其子属性。
类似
this.myObj = Object.assign({}, this.myObj, {thing: 'stuff'});
将触发对对象及其子属性的更改以呈现,而
this.myObj.thing='stuff';
不会。
要获取子属性更改以触发重新渲染,您将需要使用requestRender()
请求一个或克隆整个对象。
以下是一些示例代码,显示了基本的“属性关闭,事件增加”模型:
警告:发光元素仍处于预发布状态,语法也会更改。
parent-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);
child-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);
希望有帮助。