来自父 Promise 的子属性

问题描述

我想为我的项目创建一个导航组件。 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-elementlit-html 文档,until 指令解决shell 中的问题,但未解决 nav-element 中的问题。 相同的编码模式在 polymer 2 中运行良好(&3,尽管使用 ajax 而不是 fetch)。有谁知道如何仅使用 lit-element 来解决这个问题?

解决方法

NavElement 的构造和 chapters 属性的赋值之间有一个时间框架,其中 chaptersundefined。在组件本身而不是在 chaptersShell 指令中初始化 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。如果 chaptersPromise,则组合 untilrepeat 的正确方法应该是:

    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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...