Skip to main content

Lifecycle hooks

在 Svelte 5 中,组件的生命周期只包含两部分:其创建和其销毁。介于两者之间的一切——当某些状态更新时——与组件整体无关;只有需要响应状态变化的那些部分会被通知。这是因为底层最小的变化单位实际上不是组件,而是组件在初始化时设置的(渲染)效果。因此,不存在“更新前”/“更新后”的钩子。

挂载

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

onMount 不在服务器上渲染的组件内部运行。

<script>
	import { onMount } from 'svelte';

	onMount(() => {
		console.log('the component has mounted');
	});
</script>

如果从 onMount 返回一个函数,当组件卸载时将调用该函数。

<script>
	import { onMount } from 'svelte';

	onMount(() => {
		const interval = setInterval(() => {
			console.log('beep');
		}, 1000);

		return () => clearInterval(interval);
	});
</script>

[注意] 此行为仅在传递给 onMount同步 返回值的函数时才有效。 异步 函数始终返回一个 Promise,因此不能 同步 返回一个函数。

onDestroy

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

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

<script>
	import { onDestroy } from 'svelte';

	onDestroy(() => {
		console.log('the component is being destroyed');
	});
</script>

tick

虽然没有“更新后”的钩子,您可以使用tick来确保在继续之前 UI 已更新。tick返回一个承诺,一旦任何挂起的状态更改已应用,或者在下一次微任务中如果没有挂起的任务,则承诺解决。

<script>
	import { tick } from 'svelte';

	$effect.pre(() => {
		console.log('the component is about to update');
		tick().then(() => {
				console.log('the component just updated');
		});
	});
</script>

弃用: beforeUpdate / afterUpdate

Svelte 4 包含在组件整体更新前后运行的钩子。为了向后兼容,这些钩子在 Svelte 5 中被模拟,但不在使用 runes 的组件内部可用。

<script>
	import { beforeUpdate, afterUpdate } from 'svelte';

	beforeUpdate(() => {
		console.log('the component is about to update');
	});

	afterUpdate(() => {
		console.log('the component just updated');
	});
</script>

而不是beforeUpdate,请使用$effect.pre,而不是afterUpdate,请使用$effect——这些符文提供了更细粒度的控制,并且只对您真正感兴趣的更改做出反应。

聊天窗口示例

要实现一个当新消息出现时自动滚动到最底部的聊天窗口(但仅在你已经 滚动到最底部 的情况下),我们需要在更新之前测量 DOM。

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

使用符文,我们可以使用$effect.pre,它的行为与$effect相同,但会在 DOM 更新之前运行。只要我们在效果体内部显式引用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() {
		theme = theme === 'dark' ? 'light' : 'dark';
	}
</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}> Toggle dark mode </button>
</div>

Edit this page on GitHub llms.txt