0

0

Svelte #each 块中组件更新机制详解:键控、引用比较与性能优化

花韻仙語

花韻仙語

发布时间:2025-12-30 23:01:01

|

702人浏览过

|

来源于php中文网

原创

Svelte #each 块中组件更新机制详解:键控、引用比较与性能优化

本文深入解析 svelte `#each` 块的更新逻辑,阐明为何传递整个对象会导致不必要的组件重渲染,并给出基于键控(keyed)语义、引用比较机制和 props 设计的最佳实践。

在 Svelte 中,{#each} 块的更新行为既高效又微妙——它并非简单地“重绘整个列表”,而是依托键控(keyed)语义细粒度的 prop 变更检测协同工作。理解其底层机制,是写出高性能、可预测组件的关键。

? 键控(key)决定 DOM 节点复用,而非组件是否更新

你为 #each 指定的 key(如 (thing.id))仅用于 DOM 节点的映射与复用:Svelte 会根据 key 将旧节点与新数据项进行匹配,避免无谓的节点销毁与重建。但 key 不控制子组件内部是否触发更新。组件是否重运行 beforeUpdate/afterUpdate、是否重新计算响应式声明,完全取决于其 接收的 props 是否被判定为“已变更”

? Prop 变更判定:浅层引用比较,无深等于

Svelte 对 props 的变更检测是浅层的引用比较(shallow reference check),而非深度值比较(deep equality)。这意味着:

  • ✅ name={thing.name}(字符串):若 thing.name 值未变(如仍为 'apple'),且 thing 对象本身未被替换,Svelte 判定该 prop 未变,跳过对应 的更新。
  • ❌ name={thing}(对象):即使 thing.id 和 thing.name 完全相同,只要 thing 是一个新创建的对象引用(例如 slice() 返回新数组时,其中每个元素都是原对象的引用副本,但数组本身是新引用),Svelte 就认为 name prop 已变 —— 因为 oldName !== newName(两个不同内存地址的对象)。

这正是你观察到 beforeUpdate/afterUpdate 总是被调用的根本原因:things.slice(1) 创建了一个新数组,其内部对象虽内容相同,但数组引用变了 → #each 块内每个 都接收到一个“新”的 thing 引用 → 所有子组件均被标记为需更新。

? 正确实践:精准传参 + 合理使用 key

避免不必要更新的核心原则是:让 props 的变更信号真正反映业务意图

✅ 推荐方式:按需解构,传递原子值


{#each things as thing (thing.id)}
  
  
{/each}

此时,只要 thing.name 和 thing.id 的值不变,Svelte 就不会触发该 实例的更新周期,即使父数组被 slice、filter 或 map 重构。

TextIn Tools
TextIn Tools

是一款免费在线OCR工具,包含文字识别、表格识别,PDF转文件,文件转PDF、其他格式转换,识别率高,体验好,免费。

下载

⚠️ 若必须传对象:确保引用稳定

仅在以下场景考虑传整个对象,并务必保证引用不意外变更:

  • 对象由 store 管理且状态不可变(如 writable({}) 配合 update);
  • 使用 Object.freeze() 或 Immutable.js 等库固化引用;
  • 在 #each 外预处理,缓存对象引用(不推荐,易出错)。

? 不推荐:盲目传大对象或频繁变更对象


 

这不仅引发冗余更新,还降低代码可读性(调用方无法一眼看出组件依赖哪些字段),并可能因对象深层嵌套导致意外响应式失效。

? 补充说明:编译后的 p(ctx, [dirty]) 函数

你看到的编译输出 p(ctx, [dirty]) 是 Svelte 的更新函数(patch function),负责将变更同步到 DOM。其逻辑类似:

p(ctx, [dirty]) {
  // dirty & 1 表示 'name' prop 所在的位掩码被标记为脏
  // ctx[0].name 是当前 props 中的 name 值
  if (dirty & /*name*/ 1) {
    const newValue = /*name*/ ctx[0].name;
    // 若 newValue 是对象,此处比较的是引用!
    if (oldValue !== newValue) {
      // 触发 DOM 更新(如 set_data)
    }
  }
}

可见,p 函数本身不执行深比较;它信任 dirty 标志 —— 而 dirty 标志的设置,正源于前述的引用比较

✅ 总结:三步保障高效更新

  1. 始终为 #each 指定稳定、唯一、不可变的 key(如 thing.id),确保 DOM 节点正确复用;
  2. 子组件 export let 的 props 应尽可能原子化(字符串、数字、布尔值),避免传递整个对象,除非有强理由且能保证引用稳定;
  3. 理解 Svelte 的响应式本质:它是基于引用的、编译时静态分析的高效系统,而非运行时动态深比较 —— 设计时需顺应此范式,而非对抗它。

遵循以上原则,你的列表交互将既流畅又可预测,彻底告别“明明没改内容却疯狂重渲染”的困扰。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

248

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

205

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1434

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

609

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

546

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

539

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

157

2025.07.29

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

77

2025.08.07

桌面文件位置介绍
桌面文件位置介绍

本专题整合了桌面文件相关教程,阅读专题下面的文章了解更多内容。

0

2025.12.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.1万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号