渲染函数中的模板未解析 - LitElement

Template inside render function is not resolving - LitElement

我试图通过 ajax 调用获取列表,但在它被解析之前,render() 方法被调用并且模板片段依赖Promise 无法解析并抛出未定义的错误。

问题:在我从 Promise 获取数据之前如何显示加载程序?

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

class EmpComponent extends LitElement {
    constructor() {
        super();
        this.data = this.getEmpData();
    }

    getEmpData() {
        fetch('../../../emp-data.json')
            .then(
                function(response) {
                    if (response.status !== 200) {
                        console.log('Looks like there was a problem. Status Code: ' +
                            response.status);
                        return;
                    }

                    response.json().then(data => data);
                }
            )
            .catch(function(err) {
                console.log('Fetch Error :-S', err);
            });
    }

    render() {
        <div>
            ${this.data.map(emp => emp.active ? this.dataTemplate(emp) : '')} 
        </div>
    }
}

customElements.define('emp-component', EmpComponent);

出现此错误:

您没有在 getEmpData() 中返回任何内容,因此 this.dataundefined,因此出现错误。

请记住,如果您在 fetch() 调用之前添加 return 语句,则 this.data 将包含 Promiseuntil 指令在这种情况下可以提供帮助:

import {until} from 'lit-html/directives/until.js';

// ...

render() {
  return html`
    <div>
      ${until(
        this.data.then(data => data.map(emp => emp.active ? this.dataTemplate(emp) : ''),
        html`<p>Loading...</p>`,
      )} 
    </div>
  `;
}

第 1 步: 创建一个 js 文件 return truefalse(例如 util.js )

export function when(expression, truVal, falseVal) {
    if (expression) {
        return truVal();
    }
    if (falseVal) {
        return falseVal();
    }
    return undefined;
}

第 2 步: 在您的 js 文件中导入实用程序

import {
    LitElement,
    html
} from 'lit-element';
import {
    when
} from 'util.js'

步骤 3:static get properties 中设置一个 isLoading 属性。所以在初始加载时,我们在 constructor

中将 onload 设置为 true

import {
    LitElement,
    html
} from 'lit-element';
import {
    when
} from 'util.js'

class EmpComponent extends LitElement {
    static get properties() {
        return {
            isLoading: {
                type: Boolean
            },

        }
    }
    constructor() {
        super();
        this.isLoading = true;
    }

第 4 步: 获取数据后,我们就可以渲染 DOM。然后我们可以将 isLoading 设置为 false,然后使用 when

渲染 DOM

static get properties() {
    return {
        isLoading: {
            type: Boolean
        },
        canRender: {
            type: Boolean
        }
    }
}
constructor() {
    super();
    this.isLoading = true;
    this.canRender = false;
    this.data = this.getEmpData();
    this.isLoading = false;
    this.canRender = true;
}

render() {
    return html `
    ${when(this.isLoading,() => html`<p>Loading...</p>`)}
    ${when(this.canRender,() => html`<your-component></your-component>`)}
  `
}

这是 until 的替代解决方案。您可以从这个博客中获得更多详细信息 sabarinath blog

解决方案

我评论了您应该更改的部分。你不需要对其他导入做奇怪的事情

import { LitElement, html } from 'lit-element';
    
class EmpComponent extends LitElement
{
    constructor() {
        super();
        // you were returning a promise to an Array type...
        // this.data = this.getEmpData();
        // Correct
        this.data = [];
        this.getEmpData();
    }

    // ADD PROPS
    static get properties() {
        return {
            data: {type:Array}
        };
    }

    getEmpData() {
        fetch('../../../emp-data.json')
            .then(()=>(response) {
                    if (response.status !== 200) {
                        console.log('Looks like there was a problem. Status Code: ' +
                            response.status);
                        return;
                    }
                    // SET DATA ON RESOLVE
                    response.json().then(data => this.data = data);
                }
            )
            .catch(function(err) {
                console.log('Fetch Error :-S', err);
            });
    }

    render() {
        <div>
            $ {
                (this.data || []).map(emp => emp.active ? this.dataTemplate(emp) : '')
            } 
        </div>
    }
}

customElements.define('emp-component', EmpComponent);