列表渲染 #
一、列表渲染概述 #
1.1 Solid 的列表渲染方式 #
Solid 提供了专门的组件来高效渲染列表。
| 方式 | 说明 | 适用场景 |
|---|---|---|
For |
基于 key 的高效更新 | 对象数组 |
Index |
基于索引的更新 | 原始值数组 |
map |
原生数组方法 | 简单静态列表 |
二、For 组件 #
2.1 基本用法 #
jsx
import { For } from 'solid-js';
function UserList() {
const [users, setUsers] = createSignal([
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
]);
return (
<ul>
<For each={users()}>
{(user) => <li>{user.name}</li>}
</For>
</ul>
);
}
2.2 访问索引 #
jsx
function NumberedList() {
const [items, setItems] = createSignal(['Apple', 'Banana', 'Orange']);
return (
<ol>
<For each={items()}>
{(item, index) => (
<li>{index() + 1}. {item}</li>
)}
</For>
</ol>
);
}
2.3 响应式更新 #
jsx
function DynamicList() {
const [items, setItems] = createSignal([
{ id: 1, value: 'First' },
{ id: 2, value: 'Second' }
]);
const addItem = () => {
setItems(prev => [...prev, { id: Date.now(), value: 'New' }]);
};
const removeItem = (id) => {
setItems(prev => prev.filter(item => item.id !== id));
};
return (
<div>
<button onClick={addItem}>Add Item</button>
<ul>
<For each={items()}>
{(item) => (
<li>
{item.value}
<button onClick={() => removeItem(item.id)}>×</button>
</li>
)}
</For>
</ul>
</div>
);
}
三、Index 组件 #
3.1 基本用法 #
jsx
import { Index } from 'solid-js';
function NumberList() {
const [numbers, setNumbers] = createSignal([1, 2, 3, 4, 5]);
return (
<ul>
<Index each={numbers()}>
{(number, index) => (
<li>Index {index}: {number()}</li>
)}
</Index>
</ul>
);
}
3.2 For vs Index #
jsx
// For:值是固定的,索引是 Signal
<For each={items()}>
{(item, index) => (
<div>
Item: {item.name} {/* 固定值 */}
Index: {index()} {/* Signal */}
</div>
)}
</For>
// Index:索引是固定的,值是 Signal
<Index each={items()}>
{(item, index) => (
<div>
Item: {item()} {/* Signal */}
Index: {index} {/* 固定值 */}
</div>
)}
</Index>
四、性能优化 #
4.1 选择正确的组件 #
| 数据类型 | 推荐 | 原因 |
|---|---|---|
| 对象数组 | For | 基于 key 保持状态 |
| 原始值数组 | Index | 基于索引更新 |
| 静态列表 | map | 简单直接 |
4.2 使用 createMemo 缓存 #
jsx
function FilteredList() {
const [items, setItems] = createSignal([...]);
const [filter, setFilter] = createSignal('');
// 缓存过滤结果
const filteredItems = createMemo(() => {
const f = filter().toLowerCase();
return items().filter(item =>
item.name.toLowerCase().includes(f)
);
});
return (
<div>
<input
value={filter()}
onInput={(e) => setFilter(e.target.value)}
/>
<ul>
<For each={filteredItems()}>
{(item) => <li>{item.name}</li>}
</For>
</ul>
</div>
);
}
五、总结 #
5.1 API 选择 #
- For:对象数组,需要保持组件状态
- Index:原始值数组,可编辑的简单列表
- map:静态列表,不需要响应式更新
5.2 最佳实践 #
- 对象数组优先使用 For
- 使用 createMemo 缓存计算结果
- 大型列表考虑虚拟滚动
- 确保 key 唯一且稳定
最后更新:2026-03-28