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

SolidJS中每次变更时列表项均重新挂载是否正常?

SolidJS列表项每次变更都重新挂载是否正常?

这种情况不正常,SolidJS的<For>组件设计初衷就是实现列表的高效更新,避免不必要的组件重挂载,问题出在你的数据更新方式上。

问题原因

  • 每次点击按钮时,你通过users.map(user => ({...user, name: 'Suzy'}))生成了全新的数组和每个用户对象。<For>组件依赖数据的引用稳定性来追踪列表项,当所有项的引用都发生变化时,它会判定所有列表项都是新的,因此会卸载旧的Card组件,重新挂载新的实例,这就导致console.log('card')每次点击都会执行。
  • 改用createStore后如果还是用同样的方式替换整个对象引用,结果也会一致,因为<For>依然会把新引用识别为新的列表项。

解决方案

1. 细粒度更新数据(推荐)

使用createStore支持的细粒度更新,直接修改对象属性而不替换整个对象或数组:

import { Component, For } from 'solid-js';
import { createStore } from 'solid-js/store';

const data = [
  {name: 'Helen'},
  {name: 'Peter'},
  {name: 'Maksim'},
]

const Card: Component<{name: string}> = (props) => {
  console.log('card'); // 仅在第一次挂载时执行
  return <div>
   <span>Name: </span>
   <span>{props.name}</span>
 </div>
}

export const App: Component = () => {
  const [users, setUsers] = createStore(data);

  return (
    <>
      {/* 直接更新每个用户的name属性,不改变对象引用 */}
      <button onClick={() => setUsers(() => ({ name: 'Suzy' }))}>Click</button>
      <For each={users}>{user => <Card name={user.name} />}</For>
    </>
  );
};

这种方式下,<For>会识别到只是列表项的属性变化,而非项本身被替换,因此只会更新Card组件内对应的DOM部分,不会重新挂载整个组件。

2. 保持数据引用稳定性

如果必须生成新对象,确保列表项的引用尽可能稳定,只更新需要变化的部分。比如仅修改单个用户的属性时,不要替换整个数组,只更新目标对象的属性。

补充说明

正常情况下,当仅变更组件props的属性值而非props的引用时,SolidJS只会更新组件内对应的DOM节点,不会重新执行组件的初始化代码(即console.log只会在组件第一次挂载时运行)。

内容的提问来源于stack exchange,提问作者foloin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:23:07