Svelte基础
Svelte高阶
上下文API
特殊元素
接下来
SvelteKit基础
Shared modules
API routes
$app/state
Errors and redirects
Advanced SvelteKit
Page options
Link options
Advanced routing
Advanced loading
Environment variables
Conclusion
Svelte转场引擎还有个特别强大的功能 —— 延迟 转场,可以在多个元素之间协调转场效果。
以这个成对的待办事项列表为例,在其中切换一个待办事项会将其发送到另一个列表。在现实世界中,物体不会突然消失并在另一个地方重新出现,而是会经过一系列中间位置。使用运动效果可以大大帮助用户理解你的应用程序中发生了什么。
我们可以使用 crossfade
函数来实现这种效果,如 transition.js
中所示,该函数创建了一对名为 send
和 receive
的转场。当一个元素被“发送”时,它会寻找一个正在被“接收”的对应元素,并生成一个转场效果,将该元素变换到其对应元素的位置并淡出。当一个元素被“接收”时,会发生相反的过程。如果没有对应的元素,则使用 fallback
。
打开 TodoList.svelte
。首先,从 transition.js
中导入 send
和 receive
转场:
A particularly powerful feature of Svelte’s transition engine is the ability to defer transitions, so that they can be coordinated between multiple elements. Take this pair of todo lists, in which toggling a todo sends it to the opposite list. In the real world, objects don’t behave like that — instead of disappearing and reappearing in another place, they move through a series of intermediate positions. Using motion can go a long way towards helping users understand what’s happening in your app. We can achieve this effect using the
crossfade
function, as seen intransition.js
, which creates a pair of transitions calledsend
andreceive
. When an element is ‘sent’, it looks for a corresponding element being ‘received’, and generates a transition that transforms the element to its counterpart’s position and fades it out. When an element is ‘received’, the reverse happens. If there is no counterpart, thefallback
transition is used. OpenTodoList.svelte
. First, import thesend
andreceive
transitions from transition.js:
<script>
import { send, receive } from './transition.js';
let { todos, remove } = $props();
</script>
<script lang="ts">
import { send, receive } from './transition.js';
let { todos, remove } = $props();
</script>
然后,将它们添加到 <li>
元素并使用todo.id
作为键来匹配元素:
Then, add them to the
<li>
element, using thetodo.id
property as a key to match the elements:
<li
class={{ done: todo.done }}
in:receive={{ key: todo.id }}
out:send={{ key: todo.id }}
>
现在,当你切换项目时,它们会平滑地移动到新的位置。没有添加转场效果的元素看起来还有些生硬——我们将在下一个练习中修复这个问题。 Now, when you toggle items, they move smoothly to their new location. The non-transitioning items still jump around awkwardly — we can fix that in the next exercise.
<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>