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
嗨,小主! 上个练习我们使用延迟转场演示了把元素从一个列表转移到另一个列表。
还需要让没有转场的元素看起来不那么生硬,我们可以使用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 theflip
function — flip stands for ‘First, Last, Invert, Play’ — fromsvelte/animate
intoTodoList.svelte
:
<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:
<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:
<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 ad => milliseconds
function, whered
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.
<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>