完整教程:Svelte如何渲染列表以及如何用Diff算法极致提升性能

Hello!大家好,我是Spring Cat。这里分享的不仅是巧妙交织的代码逻辑,还有生动演绎的思考过程。我想给大家的不仅是一个答案,更是一个它为何从何而来将向何去的故事。

上次我们通过分析Svelte编译后的代码,并将其分为三个部分来理解Svelte是如何进行渲染并精准控制更新内容的。这次我们继续探索在渲染过程中列表是如何被渲染的。列表的渲染不同于普通的元素,它涉及到性能和复杂的增删改更新操作以及Diff算法,如何高效的完成这些操作是每个前端UI库的重要内容,这次我们就来一探究竟。

分析编译后的内容

当我们在.svelte文件写下这样的内容后:

<script>
	let things = $state([
		{ id: 1, name: 'apple' },
		{ id: 2, name: 'banana' },
		{ id: 3, name: 'carrot' },
		{ id: 4, name: 'doughnut' },
		{ id: 5, name: 'egg' }
	]);
</script>
{#each things as thing (thing.id)}
	
  • {thing.id} x {thing.name}
  • {/each}

    它将会被svelte编译器编译成这样的内容:

    import 'svelte/internal/disclose-version';
    import 'svelte/internal/flags/async';
    import * as $ from 'svelte/internal/client';
    var root_1 = $.from_html(`
  • `); export default function App($$anchor) { let things = $.proxy([ { id: 1, name: 'apple' }, { id: 2, name: 'banana' }, { id: 3, name: 'carrot' }, { id: 4, name: 'doughnut' }, { id: 5, name: 'egg' } ]); var fragment = $.comment(); var node = $.first_child(fragment); $.each(node, 17, () => things, (thing) => thing.id, ($$anchor, thing) => { var li = root_1(); var text = $.child(li); $.reset(li); $.template_effect(() => $.set_text(text, `${$.get(thing).id ?? ''} x ${$.get(thing).name ?? ''}`)); $.append($$anchor, li); }); $.append($$anchor, fragment); }

    还是和之前一样,先把script的部分用$的api替换掉,然后使用$的api来渲染我们声明的html模板。这里的列表就使用了$.each这个api来渲染。

    它首先使用 var fragment = $.comment() 来生成一个根节点,这个根节点里面包含了代表列表的占位符节点。

    然后通过 var node = $.first_child(fragment) 取出这个代表列表的占位符节点,接着就使用$.each来生成和渲染列表。我们先来看$.each这个api的参数:

    node锚点(Anchor),列表的所有 <li> 都会被插入到这个锚点的位置;

    17:标志位(Flags),

    • 1: 代表列表是“受控的”或处于特定模式。

    • 16: 代表 Keyed Each (带 Key 的循环)。因为写了 (thing.id),所以 Svelte 知道要用 Key 来做 Diff 算法,而不是简单的索引对比。

    () => things:数据获取函数。Svelte 将它包裹在函数里,以便在 Signal(things)变化时能够重新执行这个获取操作,触发更新;

    (thing) => thing.id:Key 获取函数。用于从每个数组项中提取唯一标识符;

    ($$anchor, thing) => { ... }:Item 渲染函数。这是渲染单个列表项的逻辑。它接收一个锚点(告诉它这个 li 插在哪)和当前的数据项 thing。

    我们传递的

    posted @ 2026-02-10 22:37  gccbuaa  阅读(13)  评论(0)    收藏  举报