【问题标题】:child property from parent Promise来自父 Promise 的子属性
【发布时间】:2021-04-14 15:28:44
【问题描述】:

我想为我的项目创建一个导航组件。 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, html, 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 解决这个问题?

【问题讨论】:

    标签: lit-element lit


    【解决方案1】:

    NavElement 的构造和chapters 属性的分配之间有一个时间范围,其中chaptersundefined。在组件本身而不是在Shelluntil 指令中初始化chapters 可能是安全的,或者至少在模板中提供一个备用值:

    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 而不是 Promiseuntil 期望的那样。如果chaptersPromise,则组合untilrepeat 的正确方法是:

      until(
        this.chaptersPromise.then(chapters => repeat(chapters, chapter => html`...`)),
        html`Loading...`,
      )
      

      但是……

    • chapters 不是Promise:父组件中的until 调用会解析它并传递结果。

    至于Shell 组件:until 以这种方式使用应该可以工作,但是它的预期用途是

    渲染占位符内容,直到最终内容可用

    [来自lit-html docs]

    要充分利用它,请使用它来临时渲染加载模板,而不是 &lt;nav-element&gt;

    render() {
      return html`
        ${until(
          this.configJson.then(chapters => html`<nav-element .chapters=${chapters}></nav-element>`),
          html`Loading chapters`,
        )}
      `;
    }
    

    另外,没什么大不了的,但这里 configJson 属性被声明为 Array 但实际上是 Promise

    【讨论】:

    • 感谢您的建议,条件数组和空数组的技巧非常有效!
    • 很高兴我能帮上忙! :)
    猜你喜欢
    • 2021-12-18
    • 1970-01-01
    • 2020-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多