You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Lit组件实现带增量异步更新的列表渲染

问题解决:Lit组件异步更新列表项不渲染的问题

核心问题分析

  1. SimpleList组件冗余代码:手动在update方法中调用requestUpdate()会触发不必要的循环更新,Lit本身会自动监听@property的变化并触发渲染。
  2. 数组引用未更新: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 12:43:19