写点什么

Svelte 最新中文文档教程(17)—— 生命周期钩子

作者:冴羽
  • 2025-02-23
    浙江
  • 本文字数:2581 字

    阅读完需:约 8 分钟

Svelte 最新中文文档教程(17)—— 生命周期钩子

前言

Svelte,一个语法简洁、入门容易,面向未来的前端框架。从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1



Svelte 以其独特的编译时优化机制著称,具有轻量级高性能易上手等特性,非常适合构建轻量级 Web 项目,也是我做个人项目的首选技术栈。


目前 Svelte 基于 Svelte 5 发布了最新的官方文档,但却缺少对应的中文文档。为了帮助大家学习 Svelte,为爱发电翻译了官方文档。


我同时搭建了 Svelte 最新的中文文档站点:https://svelte.yayujs.com ,如果需要辅助学习,也可以入手我的小册《Svelte 开发指南》,语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!


虽说是翻译,但个人并不喜欢严格遵守原文,为了保证中文阅读流畅,会删减部分语句,对难懂的部分也会另做补充解释,希望能给大家带来一个好的中文学习体验。


欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上前端大佬成长之路。

生命周期钩子

在 Svelte 5 中,组件生命周期仅由两部分组成:创建和销毁。中间的一切,比如当某些状态更新时,与整个组件无关,只有需要对状态变化做出响应的部分才会得到通知。


这是因为在底层,变化的最小单位实际上并不是组件,而是组件在初始化时设置的(渲染)effects。因此,不存在"更新前"/"更新后"这样的钩子。

onMount

onMount 函数传入一个回调函数,在组件挂载到 DOM 后立即运行。它必须在组件初始化期间被调用(但不需要位于组件内部;可以从外部模块调用)。


onMount 不会在服务端渲染的组件中运行。


<script>  import { onMount } from 'svelte';
onMount(() => { console.log('组件已挂载'); });</script>
复制代码


如果 onMount 返回一个函数,它将在组件卸载时被调用。


<script>  import { onMount } from 'svelte';
onMount(() => { const interval = setInterval(() => { console.log('beep'); }, 1000);
return () => clearInterval(interval); });</script>
复制代码


[!NOTE] 这种行为只在传递给 onMount 的函数同步返回值时才有效。async 函数总是返回一个 Promise,因此不能同步返回一个函数。

onDestroy

安排一个回调在组件卸载前立即运行。


<div class="ts-block">


function onDestroy(fn: () => any): void;
复制代码


</div>


onMountbeforeUpdateafterUpdateonDestroy 中,这是唯一一个在服务端组件内运行的。


<script>  import { onDestroy } from 'svelte';
onDestroy(() => { console.log('组件正在被销毁'); });</script>
复制代码

tick

虽然没有"更新后"钩子,但你可以使用 tick 来确保在继续之前 UI 已更新。tick 返回一个 promise,该 promise 在所有待处理的状态更改被应用后 resolve,如果没有待处理的状态更改,则在下一个微任务中 resolve。


<script>  import { tick } from 'svelte';
$effect.pre(() => { console.log('组件即将更新'); tick().then(() => { console.log('组件刚刚更新'); }); });</script>
复制代码

已废弃:beforeUpdate / afterUpdate

Svelte 4 有两个在组件整体更新前后运行的钩子。为了向后兼容,这些钩子在 Svelte 5 中被模拟实现,但在使用符文的组件中不可用。


<script>  import { beforeUpdate, afterUpdate } from 'svelte';
beforeUpdate(() => { console.log('组件即将更新'); });
afterUpdate(() => { console.log('组件刚刚更新'); });</script>
复制代码


不要使用 beforeUpdate,应该使用 $effect.pre;不要使用 afterUpdate,应该使用 $effect — 这些符文提供更细粒度的控制,只对你实际关心的更改做出响应。

聊天窗口示例

我们来实现一个聊天窗口,当出现新消息时自动滚动到底部(前提是你已经滚动到底部了),我们需要在更新 DOM 之前先测量它。


在 Svelte 4 中,我们使用 beforeUpdate 来实现,但这是一个有缺陷的方法 — 它在每次更新前都会触发,无论是否相关。在下面的示例中,我们需要引入像 updatingMessages 这样的检查,以确保在有人切换暗黑模式时不会影响滚动位置。


使用符文,我们可以使用 $effect.pre,它的行为与 $effect 相同,但在 DOM 更新之前运行。只要我们在 effect 内明确引用 messages,它就会在 messages 改变时运行,而在 theme 改变时不会运行。


因此,beforeUpdate 以及同样麻烦的小伙伴 afterUpdate 在 Svelte 5 中已被废弃。



<script>  import { ---beforeUpdate, afterUpdate,--- tick } from 'svelte';
---let updatingMessages = false;--- let theme = +++$state('dark')+++; let messages = +++$state([])+++;
let viewport;
---beforeUpdate(() => {--- +++$effect.pre(() => {+++ ---if (!updatingMessages) return;--- +++messages;+++ const autoscroll = viewport && viewport.offsetHeight + viewport.scrollTop > viewport.scrollHeight - 50;
if (autoscroll) { tick().then(() => { viewport.scrollTo(0, viewport.scrollHeight); }); }
---updatingMessages = false;--- });
function handleKeydown(event) { if (event.key === 'Enter') { const text = event.target.value; if (!text) return;
---updatingMessages = true;--- messages = [...messages, text]; event.target.value = ''; } }
function toggle() { toggleValue = !toggleValue; }</script>
<div class:dark={theme === 'dark'}> <div bind:this={viewport}> {#each messages as message} <p>{message}</p> {/each} </div>
<input +++onkeydown+++={handleKeydown} />
<button +++onclick+++={toggle}> 切换暗黑模式 </button></div>
复制代码

Svelte 中文文档

本篇已收录在掘金专栏 《Svelte 中文文档》,该系列预计 40 篇。


系统学习 Svelte,欢迎入手小册《Svelte 开发指南》。语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!


此外我还写过 JavaScript 系列TypeScript 系列React 系列Next.js 系列冴羽答读者问等 14 个系列文章, 全系列文章目录:https://github.com/mqyqingfeng/Blog


欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上前端大佬成长之路。

发布于: 刚刚阅读数: 5
用户头像

冴羽

关注

还未添加个人签名 2019-01-25 加入

分享前端技术。掘金前端领域关注数 Top 1,GitHub 中国区 Top 30,Blog 30K Star。至今写过 14 个系列文章,全网千万阅读,主页地址:yayujs.卡木

评论

发布
暂无评论
Svelte 最新中文文档教程(17)—— 生命周期钩子_vue.js_冴羽_InfoQ写作社区