Skip to main content
Svelte基础
介绍
响应
属性Props
逻辑表达式
事件
绑定
Classes和样式
动作Actions
转场
Svelte高阶
响应式进阶
内容复用
动画
高级绑定
高级转场
上下文API
特殊元素
脚本模块
接下来
SvelteKit基础
介绍
路由
加载数据
Headers和cookies
Shared modules
Forms
API routes
$app/state
Errors and redirects
Advanced SvelteKit
Hooks
Page options
Link options
Advanced routing
Advanced loading
Environment variables
Conclusion

嗨,小主! 上个练习我们使用延迟转场演示了把元素从一个列表转移到另一个列表。 还需要让没有转场的元素看起来不那么生硬,我们可以使用animate指令.
首先在TodoList.svelte中从svelte/animate引入flip‘First, Last, Invert, Play首字母缩写’ 函数:

In the previous chapter, we used deferred transitions to create the illusion of motion as elements move from one todo list to the other. To complete the illusion, we also need to apply motion to the elements that aren’t transitioning. For this, we use the animate directive. First, import the flip function — flip stands for ‘First, Last, Invert, Play’ — from svelte/animate into TodoList.svelte:

TodoList
<script>
	import { flip } from 'svelte/animate';
	import { send, receive } from './transition.js';

	let { todos, remove } = $props();
</script>
<script lang="ts">
	import { flip } from 'svelte/animate';
	import { send, receive } from './transition.js';

	let { todos, remove } = $props();
</script>

然后把它添加到<li>元素上:

Then add it to the <li> elements:

TodoList
<li
	class={{ done: todo.done }}
	in:receive={{ key: todo.id }}
	out:send={{ key: todo.id }}
	animate:flip
>

如果觉得动画效果有点慢还可以调整下duration:

The movement is a little slow in this case, so we can add a duration parameter:

TodoList
<li
	class={{ done: todo.done }}
	in:receive={{ key: todo.id }}
	out:send={{ key: todo.id }}
	animate:flip={{ duration: 200 }}
>

duration 也可以是个函数d => milliseconds, 其中d是元素经过的像素数 [!NOTE] duration can also be a d => milliseconds function, where d is the number of pixels the element has to travel

偷偷的告诉你,所有的转场和动画都是使用CSS实现的, 而不是使用JavaScript, 这样就不会阻塞主线程从而减少界面卡顿。

Note that all the transitions and animations are being applied with CSS, rather than JavaScript, meaning they won’t block (or be blocked by) the main thread.

Edit this page on GitHub

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
<script>
	import TodoList from './TodoList.svelte';
 
	const todos = $state([
		{ id: 1, done: false, description: 'write some docs' },
		{ id: 2, done: false, description: 'start writing blog post' },
		{ id: 3, done: true, description: 'buy some milk' },
		{ id: 4, done: false, description: 'mow the lawn' },
		{ id: 5, done: false, description: 'feed the turtle' },
		{ id: 6, done: false, description: 'fix some bugs' }
	]);
 
	let uid = todos.length + 1;
 
	function remove(todo) {
		const index = todos.indexOf(todo);
		todos.splice(index, 1);
	}
</script>
 
<div class="board">
	<input
		placeholder="what needs to be done?"
		onkeydown={(e) => {
			if (e.key !== 'Enter') return;
 
			todos.push({
				id: uid++,
				done: false,
				description: e.currentTarget.value
			});
 
			e.currentTarget.value = '';
		}}
	/>
 
	<div class="todo">
		<h2>todo</h2>
		<TodoList todos={todos.filter((t) => !t.done)} {remove} />
	</div>
 
	<div class="done">
		<h2>done</h2>
		<TodoList todos={todos.filter((t) => t.done)} {remove} />
	</div>
</div>
 
<style>
	.board {
		display: grid;
		grid-template-columns: 1fr 1fr;
		grid-column-gap: 1em;
		max-width: 36em;
		margin: 0 auto;
	}
 
	.board > input {
		font-size: 1.4em;
		grid-column: 1/3;
		padding: 0.5em;
		margin: 0 0 1rem 0;
	}
 
	h2 {
		font-size: 2em;
		font-weight: 200;
	}
</style>