事件处理 #
一、基本事件绑定 #
1.1 内联事件 #
svelte
<script>
let count = 0;
</script>
<button onclick={() => count += 1}>
Clicked {count} times
</button>
1.2 方法引用 #
svelte
<script>
let count = 0;
function increment() {
count += 1;
}
function add(amount) {
count += amount;
}
</script>
<button onclick={increment}>
Increment
</button>
<button onclick={() => add(5)}>
Add 5
</button>
1.3 事件对象 #
svelte
<script>
function handleClick(event) {
console.log('Event type:', event.type);
console.log('Target:', event.target);
console.log('Current target:', event.currentTarget);
}
</script>
<button onclick={handleClick}>
Click me
</button>
1.4 传递参数和事件对象 #
svelte
<script>
function handleClick(item, event) {
console.log('Item:', item);
console.log('Event:', event);
}
</script>
<button onclick={(e) => handleClick('button1', e)}>
Click with data
</button>
二、事件修饰符 #
2.1 preventDefault #
svelte
<script>
function handleSubmit() {
console.log('Form submitted');
}
</script>
<form onsubmit|preventDefault={handleSubmit}>
<input type="text" />
<button type="submit">Submit</button>
</form>
2.2 stopPropagation #
svelte
<script>
function handleDivClick() {
console.log('Div clicked');
}
function handleButtonClick() {
console.log('Button clicked');
}
</script>
<div onclick={handleDivClick}>
<button onclick|stopPropagation={handleButtonClick}>
Button
</button>
</div>
2.3 修饰符列表 #
| 修饰符 | 说明 |
|---|---|
preventDefault |
阻止默认行为 |
stopPropagation |
阻止事件冒泡 |
stopImmediatePropagation |
阻止同一元素上的其他监听器 |
capture |
使用捕获模式 |
once |
只触发一次 |
self |
只在 event.target 是当前元素时触发 |
passive |
提升滚动性能 |
nonpassive |
禁用 passive |
trusted |
只响应可信事件 |
2.4 组合修饰符 #
svelte
<button onclick|preventDefault|stopPropagation|once={handleClick}>
Multiple Modifiers
</button>
2.5 self 修饰符 #
svelte
<script>
function handleClick() {
console.log('Clicked on div itself');
}
</script>
<div onclick|self={handleClick} class="container">
<p>Clicking this paragraph won't trigger the handler</p>
<button>Clicking this button won't trigger the handler</button>
</div>
2.6 once 修饰符 #
svelte
<script>
let clicked = false;
function handleClick() {
clicked = true;
console.log('This will only log once');
}
</script>
<button onclick|once={handleClick}>
{clicked ? 'Already clicked' : 'Click once'}
</button>
三、键盘事件 #
3.1 基本键盘事件 #
svelte
<script>
let lastKey = '';
function handleKeyDown(event) {
lastKey = event.key;
console.log('Key:', event.key);
console.log('Code:', event.code);
console.log('Ctrl:', event.ctrlKey);
console.log('Shift:', event.shiftKey);
console.log('Alt:', event.altKey);
console.log('Meta:', event.metaKey);
}
</script>
<input
onkeydown={handleKeyDown}
placeholder="Press any key"
/>
<p>Last key: {lastKey}</p>
3.2 快捷键处理 #
svelte
<script>
function handleKeyDown(event) {
if (event.key === 'Enter' && event.ctrlKey) {
console.log('Ctrl + Enter pressed');
}
if (event.key === 's' && event.ctrlKey) {
event.preventDefault();
console.log('Save shortcut');
}
if (event.key === 'Escape') {
console.log('Escape pressed');
}
}
</script>
<textarea
onkeydown={handleKeyDown}
placeholder="Ctrl+Enter to submit, Ctrl+S to save"
/>
3.3 Svelte 5 语法 #
svelte
<script>
function handleKeyDown(event) {
if (event.key === 'Enter') {
console.log('Enter pressed');
}
}
</script>
<input onkeydown={handleKeyDown} />
四、鼠标事件 #
4.1 常用鼠标事件 #
svelte
<script>
let position = { x: 0, y: 0 };
let isPressed = false;
function handleMouseMove(event) {
position = {
x: event.clientX,
y: event.clientY
};
}
function handleMouseDown() {
isPressed = true;
}
function handleMouseUp() {
isPressed = false;
}
</script>
<div
onmousemove={handleMouseMove}
onmousedown={handleMouseDown}
onmouseup={handleMouseUp}
class:pressed={isPressed}
>
<p>Position: {position.x}, {position.y}</p>
<p>Status: {isPressed ? 'Pressed' : 'Released'}</p>
</div>
4.2 拖拽实现 #
svelte
<script>
let position = { x: 100, y: 100 };
let dragging = false;
let offset = { x: 0, y: 0 };
function handleMouseDown(event) {
dragging = true;
offset = {
x: event.clientX - position.x,
y: event.clientY - position.y
};
}
function handleMouseMove(event) {
if (!dragging) return;
position = {
x: event.clientX - offset.x,
y: event.clientY - offset.y
};
}
function handleMouseUp() {
dragging = false;
}
</script>
<svelte:window
onmousemove={handleMouseMove}
onmouseup={handleMouseUp}
/>
<div
class="draggable"
class:dragging
onmousedown={handleMouseDown}
style="left: {position.x}px; top: {position.y}px;"
>
Drag me
</div>
<style>
.draggable {
position: absolute;
width: 100px;
height: 100px;
background: #ff3e00;
color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: move;
user-select: none;
}
.draggable.dragging {
opacity: 0.8;
}
</style>
五、表单事件 #
5.1 输入事件 #
svelte
<script>
let text = '';
let debounceText = '';
let timer;
function handleInput(event) {
text = event.target.value;
}
function handleInputDebounced(event) {
clearTimeout(timer);
timer = setTimeout(() => {
debounceText = event.target.value;
}, 300);
}
</script>
<input oninput={handleInput} placeholder="Type something" />
<p>Live: {text}</p>
<input oninput={handleInputDebounced} placeholder="Debounced" />
<p>Debounced: {debounceText}</p>
5.2 表单提交 #
svelte
<script>
let form = {
email: '',
password: ''
};
function handleSubmit(event) {
event.preventDefault();
console.log('Form data:', form);
}
</script>
<form onsubmit={handleSubmit}>
<input
type="email"
bind:value={form.email}
required
/>
<input
type="password"
bind:value={form.password}
required
/>
<button type="submit">Submit</button>
</form>
5.3 选择事件 #
svelte
<script>
let selectedText = '';
function handleSelect(event) {
const start = event.target.selectionStart;
const end = event.target.selectionEnd;
selectedText = event.target.value.substring(start, end);
}
</script>
<textarea onselect={handleSelect} placeholder="Select some text"></textarea>
<p>Selected: {selectedText}</p>
六、自定义事件 #
6.1 创建自定义事件 #
svelte
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
function handleClick() {
dispatch('message', {
text: 'Hello from child!'
});
}
</script>
<button onclick={handleClick}>
Send Message
</button>
6.2 监听自定义事件 #
svelte
<script>
import Child from './Child.svelte';
function handleMessage(event) {
console.log('Received:', event.detail.text);
}
</script>
<Child on:message={handleMessage} />
6.3 Svelte 5 回调 Props #
svelte
<script>
let { onclick } = $props();
function handleClick() {
onclick?.({ text: 'Hello from child!' });
}
</script>
<button onclick={handleClick}>
Send Message
</button>
svelte
<script>
import Child from './Child.svelte';
function handleClick(data) {
console.log('Received:', data.text);
}
</script>
<Child onclick={handleClick} />
七、事件委托 #
7.1 列表事件委托 #
svelte
<script>
let items = [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' }
];
function handleItemClick(event) {
const target = event.target.closest('[data-id]');
if (target) {
const id = parseInt(target.dataset.id);
console.log('Clicked item:', id);
}
}
function handleDeleteClick(event) {
const target = event.target.closest('[data-action="delete"]');
if (target) {
event.stopPropagation();
const id = parseInt(target.dataset.id);
console.log('Delete item:', id);
}
}
</script>
<ul onclick={[handleItemClick, handleDeleteClick]}>
{#each items as item}
<li data-id={item.id}>
{item.name}
<button data-action="delete" data-id={item.id}>Delete</button>
</li>
{/each}
</ul>
八、触摸事件 #
8.1 基本触摸事件 #
svelte
<script>
let touchPosition = { x: 0, y: 0 };
function handleTouchStart(event) {
const touch = event.touches[0];
touchPosition = {
x: touch.clientX,
y: touch.clientY
};
}
function handleTouchMove(event) {
event.preventDefault();
const touch = event.touches[0];
touchPosition = {
x: touch.clientX,
y: touch.clientY
};
}
</script>
<div
ontouchstart={handleTouchStart}
ontouchmove|preventDefault={handleTouchMove}
class="touch-area"
>
<p>Touch position: {touchPosition.x}, {touchPosition.y}</p>
</div>
8.2 手势识别 #
svelte
<script>
let startX = 0;
let startY = 0;
let direction = '';
function handleTouchStart(event) {
startX = event.touches[0].clientX;
startY = event.touches[0].clientY;
}
function handleTouchEnd(event) {
const endX = event.changedTouches[0].clientX;
const endY = event.changedTouches[0].clientY;
const diffX = endX - startX;
const diffY = endY - startY;
if (Math.abs(diffX) > Math.abs(diffY)) {
direction = diffX > 0 ? 'right' : 'left';
} else {
direction = diffY > 0 ? 'down' : 'up';
}
}
</script>
<div
ontouchstart={handleTouchStart}
ontouchend={handleTouchEnd}
class="gesture-area"
>
<p>Swipe direction: {direction}</p>
</div>
九、完整示例:拖拽排序列表 #
svelte
<script>
let items = $state([
{ id: 1, text: 'Item 1' },
{ id: 2, text: 'Item 2' },
{ id: 3, text: 'Item 3' },
{ id: 4, text: 'Item 4' },
{ id: 5, text: 'Item 5' }
]);
let draggedItem = null;
let draggedIndex = null;
let dropTargetIndex = null;
function handleDragStart(event, item, index) {
draggedItem = item;
draggedIndex = index;
event.dataTransfer.effectAllowed = 'move';
event.target.classList.add('dragging');
}
function handleDragEnd(event) {
event.target.classList.remove('dragging');
draggedItem = null;
draggedIndex = null;
dropTargetIndex = null;
}
function handleDragOver(event) {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
}
function handleDragEnter(event, index) {
event.preventDefault();
dropTargetIndex = index;
}
function handleDrop(event, index) {
event.preventDefault();
if (draggedIndex !== null && draggedIndex !== index) {
const newItems = [...items];
newItems.splice(draggedIndex, 1);
newItems.splice(index, 0, draggedItem);
items = newItems;
}
draggedItem = null;
draggedIndex = null;
dropTargetIndex = null;
}
</script>
<ul class="sortable-list">
{#each items as item, index (item.id)}
<li
draggable="true"
ondragstart={(e) => handleDragStart(e, item, index)}
ondragend={handleDragEnd}
ondragover={handleDragOver}
ondragenter={(e) => handleDragEnter(e, index)}
ondrop={(e) => handleDrop(e, index)}
class:drop-target={dropTargetIndex === index}
>
{item.text}
</li>
{/each}
</ul>
<style>
.sortable-list {
list-style: none;
padding: 0;
}
li {
padding: 1rem;
margin: 0.5rem 0;
background: #f5f5f5;
border: 1px solid #ddd;
border-radius: 4px;
cursor: move;
transition: transform 0.2s, box-shadow 0.2s;
}
li.dragging {
opacity: 0.5;
transform: scale(1.02);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
li.drop-target {
border-color: #ff3e00;
background: #fff3f0;
}
</style>
十、总结 #
| 事件类型 | 说明 |
|---|---|
onclick |
点击事件 |
onkeydown |
键盘按下 |
onkeyup |
键盘释放 |
onmousedown |
鼠标按下 |
onmouseup |
鼠标释放 |
onmousemove |
鼠标移动 |
oninput |
输入事件 |
onsubmit |
表单提交 |
onchange |
值改变 |
事件处理要点:
- 使用修饰符简化常见操作
- 合理使用事件委托
- 注意内存泄漏,及时清理
- 自定义事件用于组件通信
- 触摸事件需要考虑移动端兼容
最后更新:2026-03-28