问题描述
我想为我的项目创建一个导航组件。 shell
获取包含章节信息的 json,这些信息被传递给 nav-element
,后者递归调用自身以呈现导航树。
shell.js
import { LitElement,html,css } from 'lit-element';
import {until} from 'lit-html/directives/until.js';
import './nav-element.js';
export class Shell extends LitElement {
static get properties() {
return {
configjson : { type: Array }
};
}
constructor() {
super();
this.configjson = fetch('./src/convertjson_test.json').then(res => res.json());
}
render() {
return html`
<main>
some content
<nav-element .chapters=${until(this.configjson,[])} root></nav-element>
</main>
`;
}
}
customElements.define('shell',Shell);
导航元素.js
import { LitElement,css } from 'lit-element';
import {until} from 'lit-html/directives/until.js';
import {repeat} from 'lit-html/directives/repeat.js';
export class NavElement extends LitElement {
static get properties() {
return {
chapters: {type: Array},root: {type: Boolean} //to mark the root node
};
}
static get styles() {
return css`
.navheader {
display: none;
}
.navheader[active] {
display: block;
}
`;
}
render() {
return html`
<div class="navHeader" ?active="${this.root}">header</div>
${until(repeat(this.chapters,(chapter) => chapter.pos,(chapter) => html`<div>${chapter.n}<nav-element .chapters=${chapter.c}></nav-element></div>`))}
`;
}
}
customElements.define('nav-element',NavElement);
问题是,configjson
Promise 作为属性传递并且在调用 nav-element
时尚未解决,所以我收到错误:
Uncaught (in promise) TypeError: this.chapters is undefined
搜索了所有 lit-element
和 lit-html
文档,until
指令解决了 shell
中的问题,但未解决 nav-element
中的问题。
相同的编码模式在 polymer 2
中运行良好(&3,尽管使用 ajax 而不是 fetch)。有谁知道如何仅使用 lit-element 来解决这个问题?
解决方法
在 NavElement
的构造和 chapters
属性的赋值之间有一个时间框架,其中 chapters
是 undefined
。在组件本身而不是在 chapters
的 Shell
指令中初始化 until
可能是安全的,或者至少在模板中提供一个回退值:
export class NavElement extends LitElement {
static get properties() {
return {
chapters: {type: Array},// ...
};
}
constructor() {
super();
this.chapters = [];
}
// or
render() {
return html`
...
${repeat(this.chapters || [],chapter => ...)}
`;
}
}
此外,您已经(正确地)将 chapters
属性声明为 Array
,但是您将 repeat
指令包装在 until
中(就好像它是Promise
我猜?)。这里有两件事正在发生:
-
repeat()
调用返回一个DirectiveFn
而不是Promise
所期望的until
。如果chapters
是Promise
,则组合until
和repeat
的正确方法应该是:until( this.chaptersPromise.then(chapters => repeat(chapters,chapter => html`...`)),html`Loading...`,)
但是……
-
chapters
不是Promise
:父组件中的until
调用解析它并传递结果。
至于 Shell
组件:以这种方式使用的 until
应该可以工作,但其预期用途是
渲染占位符内容,直到最终内容可用
[来自lit-html docs]
要充分利用它,请使用它来临时呈现加载模板而不是 <nav-element>
:
render() {
return html`
${until(
this.configJson.then(chapters => html`<nav-element .chapters=${chapters}></nav-element>`),html`Loading chapters`,)}
`;
}
另外,没什么大不了的,但这里的 configJson
属性被声明为 Array
但实际上是一个 Promise
。