首页 / Svelte 5 入门教程 / 事件转发与回调 Props

Svelte 5 入门教程

事件转发与回调 Props

本教程共 50 篇 · 第 19 篇 · 更新于 2026-08-05 · 约 6 分钟阅读

SvelteSvelte 5回调Props事件转发$host组件通信

本节目标:学会 Svelte 5 中组件通信的新方式——回调 Props 模式,理解事件转发机制,了解 $host() rune 在自定义元素中的用途。

Svelte 5 的组件通信变了

在 Svelte 4 里,组件要往外发事件,你得用 createEventDispatcher 创建一个派发器,然后调用 dispatch('事件名') 来发事件。这套机制在 Svelte 5 中被废弃了。

Svelte 5 的思路很简单:事件就是函数,函数就是 Prop。把回调函数当作 Prop 传进去,子组件直接调用就行。

打个比方,以前你要给同事传话,得通过前台转接(createEventDispatcher)。现在直接把同事电话给你(回调 Prop),你自己打过去就行,简单直接。

回调 Props 模式

回调 Props 的核心思想:父组件把一个函数传给子组件,子组件在合适的时机调用这个函数。

<!-- Stepper.svelte -->
<script>
	let { onincrement, ondecrement } = $props();
</script>

<button onclick={ondecrement}>减一</button>
<button onclick={onincrement}>加一</button>
<!-- App.svelte -->
<script>
	import Stepper from './Stepper.svelte';

	let count = $state(0);
</script>

<Stepper
	onincrement={() => count += 1}
	ondecrement={() => count -= 1}
/>

<p>当前计数:{count}</p>

你看到了吗?子组件通过 $props() 接收 onincrementondecrement 两个函数,然后在按钮点击时调用它们。父组件传入具体的逻辑。

Note

回调 Props 的命名习惯是以 on 开头,比如 onclickonsubmitonchange。这样跟原生事件属性风格一致,一看就知道是事件回调。

回调 Props 传参

回调函数可以携带数据。子组件调用时传入参数,父组件就能收到。

<!-- SearchBox.svelte -->
<script>
	let keyword = $state('');

	let { onsearch } = $props();

	function handleKeydown(event) {
		if (event.key === 'Enter') {
			// 把搜索词传给父组件
			onsearch?.(keyword);
		}
	}
</script>

<input
	bind:value={keyword}
	onkeydown={handleKeydown}
	placeholder="输入关键词后回车"
/>
<!-- App.svelte -->
<script>
	import SearchBox from './SearchBox.svelte';

	let results = $state([]);

	function handleSearch(keyword) {
		// 收到子组件传来的关键词
		console.log('搜索:', keyword);
		results = ['结果1', '结果2'];
	}
</script>

<SearchBox onsearch={handleSearch} />

<ul>
	{#each results as item}
		<li>{item}</li>
	{/each}
</ul>
Tip

用可选链 onsearch?.() 调用回调是个好习惯。这样即使父组件没传这个 Prop,也不会报错。

事件转发

有时候你的组件是个”中间人”——它包裹了一个子组件,需要把子组件的事件转发给更上层的父组件。

在 Svelte 5 里,事件转发可以用展开语法实现。把接收到的 Props 原样展开到子组件上就行。

<!-- Button.svelte -->
<script>
	let { onclick, children, ...rest } = $props();
</script>

<button {onclick} {...rest}>
	{@render children?.()}
</button>
<!-- FancyButton.svelte(中间组件) -->
<script>
	import Button from './Button.svelte';

	// 把所有 props 原样传给 Button
	let props = $props();
</script>

<Button {...props} class="fancy" />
<!-- App.svelte -->
<script>
	import FancyButton from './FancyButton.svelte';

	function handleClick() {
		console.log('点击事件穿过了两层组件');
	}
</script>

<!-- onclick 会从 App 传到 FancyButton,再传到 Button -->
<FancyButton onclick={handleClick}>点我</FancyButton>
Note

因为 Svelte 5 的事件就是普通属性,所以事件转发本质上就是属性转发。用 {...props} 展开语法就能把所有事件回调一并传下去,非常方便。

对比 Svelte 4 的事件转发

来看看 Svelte 4 是怎么做事件转发的,你就知道 Svelte 5 有多简洁了。

<!-- Svelte 4 写法:Button.svelte -->
<button on:click>转发 click 事件</button>

<!-- Svelte 4 写法:FancyButton.svelte -->
<script>
	import Button from './Button.svelte';
</script>

<!-- 需要手动转发每个事件:on:click 不带值表示转发 -->
<Button on:click />

Svelte 4 里你得为每个事件都写一条转发指令。Svelte 5 用展开语法一行搞定,所有 on 开头的属性自动转发。

$host() Rune

$host() 是一个特殊的 rune,专门用于把 Svelte 组件编译成自定义元素(Web Components)时使用。它返回宿主元素,让你能在自定义元素上派发事件。

<!-- Stepper.svelte -->
<svelte:options customElement="my-stepper" />

<script>
	function dispatch(type) {
		// $host() 返回自定义元素的 DOM 节点
		$host().dispatchEvent(new CustomEvent(type));
	}
</script>

<button onclick={() => dispatch('decrement')}>减一</button>
<button onclick={() => dispatch('increment')}>加一</button>

使用这个自定义元素时,监听事件的方式跟原生 HTML 元素一样:

<!-- App.svelte -->
<script>
	import './Stepper.svelte';

	let count = $state(0);
</script>

<!-- 监听自定义元素的事件 -->
<my-stepper
	ondecrement={() => count -= 1}
	onincrement={() => count += 1}
></my-stepper>

<p>计数:{count}</p>
Note

$host() 仅在组件被编译为自定义元素时可用。如果你在普通组件中调用它会报错。自定义元素是 Svelte 与原生 Web Components 交互的桥梁。

回调 Props vs Store vs Context

你可能会问:组件之间通信方式这么多,什么时候用回调 Props?

方式适用场景数据流向
回调 Props父子组件,事件通知子 -> 父
bind: 绑定父子组件,双向同步父 <-> 子
Store跨组件共享状态任意方向
Context API祖先到后代传值祖先 -> 后代

简单来说,父给子传数据用 Props,子给父发通知用回调 Props,跨多层组件共享状态用 Store 或 Context。

本节回顾

  • Svelte 5 废弃了 createEventDispatcher,用回调 Props 模式替代
  • 回调 Props 就是把函数当作 Prop 传给子组件,子组件直接调用
  • 事件转发通过 {...props} 展开语法实现,所有事件属性自动转发
  • $host() rune 仅用于自定义元素场景,返回宿主 DOM 节点
  • 回调 Props 命名以 on 开头,与原生事件属性风格保持一致