基于Lit组件实现带增量异步更新的列表渲染
问题解决:Lit组件异步更新列表项不渲染的问题
核心问题分析
- SimpleList组件冗余代码:手动在
update方法中调用requestUpdate()会触发不必要的循环更新,Lit本身会自动监听@property的变化并触发渲染。 - 数组引用未更新:FooList中直接修改数组的索引项
this.data[i],由于数组是引用类型,Lit的浅比较机制会认为data属性没有变化,因此不会触发组件更新。
修复方案
1. 简化SimpleList组件
移除多余的update方法,让Lit自动处理属性变化的渲染逻辑。
2. 修改FooList的数据更新方式
异步获取到value后,通过创建新数组的方式更新data属性,确保数组引用发生变化,触发Lit的属性检测和渲染更新。同时优化异步逻辑,避免立即清空数组导致的闪烁。
修改后的完整代码
Simple-List.ts
import { html, LitElement } from "lit"; import { customElement, property } from "lit/decorators.js"; export type SimpleListItem = { name: string, value: string }; @customElement("simple-list") export class SimpleList extends LitElement { @property({ type: Array, attribute: false }) items: SimpleListItem[] = []; render() { return html`<ul>${this.items.map((item) => html`<li>${item.name}: ${item.value}</li>`)}</ul>`; } }
Foo-List.ts
import { html, LitElement } from "lit"; import { customElement, property } from "lit/decorators.js"; import "./Simple-List"; import { SimpleListItem } from "./Simple-List"; async function getValue(name: string): Promise<string> { return new Promise((resolve) => { setTimeout(() => { resolve(`Value for ${name}`); }, Math.random() * 1000); }); } @customElement("foo-list") export class MyFoo extends LitElement { @property({ type: Array }) names: string[] = []; @property({ type: Array, attribute: false }) data: SimpleListItem[] = []; constructor() { super(); } // 改用willUpdate生命周期,更适合处理属性变化后的逻辑 willUpdate(changedProperties: Map<string, unknown>) { if (changedProperties.has("names")) { this.getDataAndUpdate(); } } async getDataAndUpdate() { // 初始化所有项为loading状态,直接赋值新数组 this.data = this.names.map(name => ({ name, value: "loading..." })); // 遍历每个name,异步获取value并更新 for (let i = 0; i < this.names.length; i++) { const name = this.names[i]; try { const value = await getValue(name); // 创建新数组,替换对应项,确保引用变化 this.data = [ ...this.data.slice(0, i), { name, value }, ...this.data.slice(i + 1) ]; } catch (err) { // 处理错误情况 this.data = [ ...this.data.slice(0, i), { name, value: "加载失败" }, ...this.data.slice(i + 1) ]; } } } render() { return html` <simple-list .items=${this.data}></simple-list> `; } }
关键优化点说明
- 使用
willUpdate替代自定义update逻辑:willUpdate是Lit推荐的处理属性变化前的生命周期钩子,比手动在update中判断更规范。 - 数组更新方式:通过扩展运算符
...创建新数组,替换目标项,确保data属性的引用发生变化,触发Lit的自动更新。 - 错误处理:添加try/catch捕获异步请求失败的情况,提升组件健壮性。
内容的提问来源于stack exchange,提问作者rovyko
相关产品推荐
相关产品推荐

