Svelte 5 入门教程
use: 指令(Actions)
本教程共 50 篇 · 第 22 篇 · 更新于 2026-08-05 · 约 5 分钟阅读
SvelteSvelte 5use指令ActionsDOM操作
本节目标:理解什么是 Action,学会编写 Action 函数封装 DOM 操作,掌握参数传递和清理机制,实现 clickOutside 和 tooltip 等实用功能。
Action 是什么
Action 是一种函数,在元素被挂载到 DOM 时自动调用。你用它来封装那些需要直接操作 DOM 的逻辑。
打个比方,Action 就像给元素配了个贴身管家。元素一挂载,管家就到位,帮你处理各种杂事。元素卸载时,管家也会做好收尾工作。
<script>
function myaction(node) {
// node 就是挂载的 DOM 元素
console.log('元素已挂载', node);
$effect(() => {
// 设置逻辑放这里
return () => {
// 清理逻辑放这里
};
});
}
</script>
<div use:myaction>我有一个 Action</div>
最简单的 Action
来写一个让元素挂载后变色的 Action。
<script>
function highlight(node) {
$effect(() => {
node.style.backgroundColor = 'yellow';
node.style.padding = '2px 4px';
return () => {
// 元素卸载时恢复
node.style.backgroundColor = '';
node.style.padding = '';
};
});
}
</script>
<p use:highlight>这段文字会被高亮</p>
传参数
Action 可以接收参数。用 use:action={参数} 的语法传入。
<script>
let color = $state('lightblue');
function setColor(node, color) {
$effect(() => {
node.style.backgroundColor = color;
return () => {
node.style.backgroundColor = '';
};
});
}
</script>
<!-- 传入参数 -->
<div use:setColor={color}>背景色跟着变量变</div>
<input bind:value={color} />
NoteAction 函数只在元素挂载时调用一次。参数变化不会重新调用 Action,但
$effect内部的逻辑会响应参数变化。
实战:clickOutside 点击外部
一个经典场景:弹出一个下拉菜单,点击外面时自动关闭。
<script>
let showMenu = $state(false);
function clickOutside(node, callback) {
$effect(() => {
function handleClick(event) {
// 如果点击的不是当前元素及其子元素
if (!node.contains(event.target)) {
callback();
}
}
document.addEventListener('click', handleClick, true);
return () => {
document.removeEventListener('click', handleClick, true);
};
});
}
</script>
<div use:clickOutside={() => showMenu = false}>
<button onclick={() => showMenu = !showMenu}>菜单</button>
{#if showMenu}
<ul style="position: absolute; background: white; border: 1px solid #ccc;">
<li>选项一</li>
<li>选项二</li>
<li>选项三</li>
</ul>
{/if}
</div>
Tip
clickOutside是最常用的 Action 之一。你可以把它抽到一个单独的.svelte.js文件中复用。
实战:tooltip 提示
另一个常见场景:鼠标悬浮显示提示文字。
<script>
function tooltip(node, text) {
let tooltipEl;
$effect(() => {
function show() {
tooltipEl = document.createElement('div');
tooltipEl.textContent = text;
tooltipEl.style.cssText = `
position: absolute;
background: black;
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
z-index: 9999;
`;
document.body.appendChild(tooltipEl);
}
function hide() {
tooltipEl?.remove();
}
node.addEventListener('mouseenter', show);
node.addEventListener('mouseleave', hide);
return () => {
node.removeEventListener('mouseenter', show);
node.removeEventListener('mouseleave', hide);
hide();
};
});
}
</script>
<button use:tooltip={'这是一个提示'}>
悬浮看提示
</button>
旧版返回值写法
在 Svelte 5 的 $effect rune 出现之前,Action 通过返回对象来管理更新和销毁。这种写法仍然支持,但推荐用 $effect。
<script>
// 旧写法(仍支持,但不推荐)
function oldAction(node, param) {
// 挂载时执行
return {
update(newParam) {
// 参数变化时执行
},
destroy() {
// 元素卸载时执行
}
};
}
</script>
<div use:oldAction={'参数'}>旧写法</div>
| 对比项 | $effect 写法(推荐) | 旧写法 update/destroy |
|---|---|---|
| 参数更新 | 自动响应 | 需要手动写 update |
| 清理逻辑 | return 清理函数 | destroy 方法 |
| Runes 兼容 | 完全兼容 | 兼容但不推荐 |
Action 的类型标注
用 TypeScript 时,可以用 Action 类型来标注。
<script lang="ts">
import type { Action } from 'svelte/action';
const clickOutside: Action<HTMLElement, () => void> = (node, callback) => {
$effect(() => {
function handleClick(event: MouseEvent) {
if (!node.contains(event.target as Node)) {
callback?.();
}
}
document.addEventListener('click', handleClick, true);
return () => document.removeEventListener('click', handleClick, true);
});
};
</script>
<div use:clickOutside={() => console.log('点了外面')}>
点外面试试
</div>
Note在 Svelte 5.29 及以上版本,官方推荐使用
@attach附件(Attachments)替代use:指令,因为附件更灵活、更可组合。但use:仍然完全可用,大量现有代码也在使用。
本节回顾
- Action 是元素挂载时自动调用的函数,用于封装 DOM 操作
- 用
use:actionName绑定,用use:actionName={参数}传参 - 推荐在 Action 内部用
$effect管理副作用和清理逻辑 clickOutside和tooltip是两个最经典的 Action 应用场景- 旧版
update/destroy返回值写法仍支持,但推荐用$effect - TypeScript 中可用
Action类型进行标注