Skip to main content
基本 Svelte
介绍
反应性
属性
逻辑
事件
绑定
类和样式
动作
转换
高级 Svelte
高级反应性
重用内容
运动
高级绑定
高级转换
上下文 API
特殊元素
<script module>
后续步骤
基本 SvelteKit
介绍
路由
加载数据
标题和 cookie
共享模块
表单
API 路由
$app/state
错误和重定向
高级 SvelteKit
钩子
页面选项
链接选项
高级路由
高级加载
环境变量
结论

因为我们使用的是 <form>,所以即使用户没有 JavaScript(这种情况比你想象的更常见),我们的应用也可以工作。这很好,因为这意味着我们的应用具有弹性。

¥Because we’re using <form>, our app works even if the user doesn’t have JavaScript (which happens more often than you probably think). That’s great, because it means our app is resilient.

大多数情况下,用户确实有 JavaScript。在这些情况下,我们可以逐步增强体验,就像 SvelteKit 使用客户端路由逐步增强 <a> 元素一样。

¥Most of the time, users do have JavaScript. In those cases, we can progressively enhance the experience, the same way SvelteKit progressively enhances <a> elements by using client-side routing.

$app/forms 导入 enhance 函数...

¥Import the enhance function from $app/forms...

src/routes/+page
<script>
	import { enhance } from '$app/forms';

	let { data, form } = $props();
</script>
<script lang="ts">
	import { enhance } from '$app/forms';

	let { data, form } = $props();
</script>

...并将 use:enhance 指令添加到 <form> 元素:

¥...and add the use:enhance directive to the <form> elements:

src/routes/+page
<form method="POST" action="?/create" use:enhance>
src/routes/+page
<form method="POST" action="?/delete" use:enhance>

这就是全部内容!现在,当启用 JavaScript 时,use:enhance 将模拟浏览器原生行为,但整页重新加载除外。它将:

¥And that’s all it takes! Now, when JavaScript is enabled, use:enhance will emulate the browser-native behaviour except for the full-page reloads. It will:

  • 更新 form prop

    ¥update the form prop

  • 在成功响应时使所有数据无效,导致 load 函数重新运行

    ¥invalidate all data on a successful response, causing load functions to re-run

  • 在重定向响应中导航到新页面

    ¥navigate to the new page on a redirect response

  • 如果发生错误,则渲染最近的错误页面

    ¥render the nearest error page if an error occurs

现在我们正在更新页面而不是重新加载它,我们可以对诸如过渡之类的东西进行一些花哨的操作:

¥Now that we’re updating the page rather than reloading it, we can get fancy with things like transitions:

src/routes/+page
<script>
	import { fly, slide } from 'svelte/transition';
	import { enhance } from '$app/forms';

	let { data, form } = $props();
</script>
<script lang="ts">
	import { fly, slide } from 'svelte/transition';
	import { enhance } from '$app/forms';

	let { data, form } = $props();
</script>
src/routes/+page
<li in:fly={{ y: 20 }} out:slide>...</li>
上一页 下一页
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<script>
	let { data, form } = $props();
</script>
 
<div class="centered">
	<h1>todos</h1>
 
	{#if form?.error}
		<p class="error">{form.error}</p>
	{/if}
 
	<form method="POST" action="?/create">
		<label>
			add a todo:
			<input
				name="description"
				value={form?.description ?? ''}
				autocomplete="off"
				required
			/>
		</label>
	</form>
 
	<ul class="todos">
		{#each data.todos as todo (todo.id)}
			<li>
				<form method="POST" action="?/delete">
					<input type="hidden" name="id" value={todo.id} />
					<span>{todo.description}</span>
					<button aria-label="Mark as complete"></button>
				</form>
			</li>
		{/each}
	</ul>
</div>
 
<style>
	.centered {
		max-width: 20em;
		margin: 0 auto;
	}
 
	label {
		width: 100%;
	}
 
	input {
		flex: 1;
	}
 
	span {
		flex: 1;
	}
 
	button {
		border: none;
		background: url(./remove.svg) no-repeat 50% 50%;
		background-size: 1rem 1rem;
		cursor: pointer;
		height: 100%;
		aspect-ratio: 1;
		opacity: 0.5;
		transition: opacity 0.2s;
	}
 
	button:hover {
		opacity: 1;
	}
 
	.saving {
		opacity: 0.5;
	}
</style>