LitElement中Promise未解析时如何显示加载器?
Hey there, let's work through your problem step by step. The core issues here are that your async data fetch isn't properly integrated with LitElement's reactive system, and you're trying to render data before it's available. Here's how to fix it and add a loader:
1. Fix the getEmpData Function
First, your current function doesn't return the Promise from fetch, which means this.data ends up as undefined right away. Let's fix that and properly chain the Promise:
getEmpData() { return fetch('../../../emp-data.json') .then(response => { if (response.status !== 200) { throw new Error(`Looks like there was a problem. Status Code: ${response.status}`); } return response.json(); // Return parsed JSON to continue the Promise chain }) .catch(err => { console.error('Fetch Error :-S', err); return []; // Return empty array to avoid map errors later }); }
2. Add Reactive Properties for Data & Loading State
LitElement relies on reactive properties to trigger re-renders when data changes. Let's define data and isLoading as reactive properties, and initialize them properly:
import { LitElement, html } from 'lit-element'; class EmpComponent extends LitElement { // Define reactive properties static get properties() { return { data: { type: Array }, isLoading: { type: Boolean } }; } constructor() { super(); this.data = []; // Initialize with empty array to avoid map errors this.isLoading = true; // Start in loading state }
3. Fetch Data in the Right Lifecycle Hook
Don't fetch data in the constructor—wait until the component has been first rendered using firstUpdated (LitElement's lifecycle hook for post-first-render actions):
firstUpdated() { // Fetch data once the component is mounted this.getEmpData().then(fetchedData => { this.data = fetchedData; // Update reactive property to trigger re-render this.isLoading = false; // Turn off loading state }); }
4. Update render to Show Loader or Data
Now adjust your render method to conditionally show the loader while data is being fetched, and render the employee data once it's ready:
render() { return html` <div> ${this.isLoading ? html`<div class="loader">Loading employee data...</div>` : html`${this.data.map(emp => emp.active ? this.dataTemplate(emp) : '')}`} </div> `; } // Example template for individual employees dataTemplate(emp) { return html` <div class="employee-card"> <h3>${emp.name}</h3> <p>Role: ${emp.role}</p> <p>Department: ${emp.department}</p> </div> `; } } customElements.define('emp-component', EmpComponent);
Why This Works
- Reactive Properties: When
this.dataorthis.isLoadingchanges, LitElement automatically triggers a re-render of your component. - Initial Empty Array: Prevents the
mapfunction from throwing an error whenthis.datais initially empty. - Loading State: Gives users feedback while data is being fetched instead of showing a broken or empty page.
- Proper Error Handling: Returning an empty array on fetch failure ensures your component doesn't crash, and you can extend this to show an error message if needed.
内容的提问来源于stack exchange,提问作者Hitesh Misro

