Svelte中Material风格Snackbar动画问题:实现单次显隐效果
解决Svelte Material风格Snackbar点击关闭后重复出现的问题
问题根源
你当前的代码通过{#if show}和{:else}渲染了两个独立的Snackbar元素:当show从true切换到false时,第一个元素执行模糊消失过渡,但第二个元素会立即挂载并执行飞入动画,点击按钮又会切换回第一个元素,导致循环往复的问题。
解决方案
只保留一个Snackbar元素,利用Svelte的in:和out:过渡分别定义进入和退出动画,通过show状态控制元素的挂载/卸载,避免重复渲染。
完整修正代码
Svelte组件代码
<script lang="ts"> import '../css/snackbar.css'; import { linear } from 'svelte/easing'; import { blur, fly } from 'svelte/transition'; let show = true; export let message: string; export let actionText: string = 'Dismiss'; const transitionOptions = { duration: 350, easing: linear }; </script> {#if show} <div class="snackbar" class:snackbar-active={Boolean(message)} in:fly={{ ...transitionOptions, y: 600, opacity: 1 }} out:blur={transitionOptions} > <div class="snackbar-text"> {message} </div> <button class="link" on:click={() => (show = false)}>{actionText}</button> </div> {/if}
修正后的CSS代码
.snackbar { align-items: center; background: var(--project-color-surface-variant); border-radius: 0.5rem; color: #fff; display: inline-flex; justify-content: space-between; padding: 0.625rem 1.25rem; position: fixed; bottom: 1.25rem; left: 50%; transform: translateX(-50%); width: fit-content; z-index: 999; } .snackbar .link { background: none; border: none; color: var(--project-color-secondary); cursor: pointer; padding-left: 1.25rem; }
关键改动说明
- 移除双分支渲染:只在
show为true时渲染单个Snackbar元素,避免切换状态时重复创建DOM节点 - 分离过渡逻辑:
in:fly:定义进入动画,从屏幕底部(y:600)飞入,符合Material Design的Snackbar出现规范out:blur:定义退出动画,点击关闭按钮后执行模糊消失效果
- 修复CSS布局错误:
- 修正
align-items和justify-content的语法错误,实现内容水平分布 - 添加底部定位和居中样式,让Snackbar固定在屏幕底部居中位置
- 提高
z-index确保Snackbar显示在其他内容上层
- 修正
内容的提问来源于stack exchange,提问作者TheGreatZackAttack
相关产品推荐
相关产品推荐

