Svelte crossfade动画仅在跨文件导入时生效问题咨询
Svelte crossfade触发fallback动画的问题解决
问题原因
你遇到的问题核心是组件实例化时重复创建crossfade配对:
- 当在组件内部直接定义
[send, receive] = crossfade(...),每个组件实例(比如页面上的已完成/待办两个列表组件)都会生成独立的crossfade通道,不同实例的send和receive不属于同一配对组。 - 当元素在两个组件间转移时,接收方的
receive无法识别发送方的send信号,就会触发fallback动画。
解决方案
把crossfade的初始化逻辑抽离到单独的模块文件,利用ES模块的单例特性,让所有组件共享同一组send/receive函数:
- 创建
crossfade.js文件:
import { quintOut } from "svelte/easing"; import { crossfade } from "svelte/transition"; export const [send, receive] = crossfade({ duration: 300, fallback(node, params) { const style = getComputedStyle(node); const transform = style.transform === "none" ? "" : style.transform; return { duration: 600, easing: quintOut, css: (t) => ` transform: ${transform} scale(${t}); opacity: ${t} `, }; }, });
- 在组件中导入使用:
<script> import { send, receive } from './crossfade.js'; export let todos; export let done; </script> <ul> {#each $todos.filter(todo => todo.done === done) as todo (todo.id)} <label> <li class:done in:receive={{ key: todo.id }} out:send={{ key: todo.id }}> <input type="checkbox" checked={todo.done} on:change={(e) => todos.mark(todo, e.currentTarget.checked)} /> <span>{todo.description}</span> </li> </label> {/each} </ul> <style> .done { opacity: 0.6; text-decoration: line-through; } ul { list-style-type: none; margin: 0; padding: 0; width: 100%; } li { padding: 1rem; margin: 1.3rem; font-size: 1.2rem; box-shadow: 0 3px 10px rgb(0 0 0 / 0.2); border-radius: 3px; } </style>
原理说明
ES模块在浏览器/构建工具中是单例模式,crossfade.js只会被执行一次,生成的send和receive是同一组配对函数。所有组件实例导入后共用这组函数,当元素在不同组件间转移时,send发出的信号能被receive正确识别,从而执行正常的过渡动画,不会触发fallback。
内容的提问来源于stack exchange,提问作者Deekshith Shetty
相关产品推荐
相关产品推荐

