Slidev 导航方向变体详解:用 forward/backward 为前进与后退应用不同样式和动画
【免费下载链接】slidevPresentation Slides for Developers项目地址: https://gitcode.com/GitHub_Trending/sl/slidev
本文讲解 Slidev 自 v0.48.0 引入的导航方向变体(Navigation Direction Variants):通过在幻灯片容器上动态挂载.slidev-nav-go-forward与.slidev-nav-go-backward类,以及配套的 UnoCSSforward:/backward:变体前缀,你可以为"前进"和"后退"两种导航方向编写完全不同的 CSS 样式与过渡动画。读完本文,你将理解这两个类在渲染管线中的来源与挂载时机,掌握纯 CSS 与 UnoCSS 两种写法,并能实现"进入慢、离开快"这类不对称动画效果。
功能定位:为什么需要方向敏感的样式
在演讲中翻页时,观众常希望"进入下一页"的动画更从容(例如元素依次带延迟淡入),而"回退到上一页"时则希望动画立即完成,避免等待感。Slidev 的 v-click 动画机制本身不区分导航方向,因此官方在 v0.48.0 提供了方向变体能力:导航发生时,幻灯片容器会自动带上方向类,任何后代元素(尤其是.slidev-vclick-target动画目标)都可以据此应用条件化样式。
该功能在仓库中的完整文档见 docs/features/direction-variant.md,AI 技能参考见 skills/slidev/references/style-direction.md。
两类方向类从哪里来:源码中的挂载机制
从源码结构看,方向类挂载在幻灯片总容器(#slideshow)上,由clicksDirection这个响应式引用驱动。
在 packages/client/internals/SlidesShow.vue 中,承载全部幻灯片的容器组件绑定了这样的 class:
<component :is="..." id="slideshow" tag="div" :class="{ 'slidev-nav-go-forward': clicksDirection > 0, 'slidev-nav-go-backward': clicksDirection < 0, }" @after-leave="onAfterLeave" >clicksDirection定义在 packages/client/composables/useNav.ts 中,初始值为0。所有导航入口函数都会在触发路由变更前先设置方向值:
next()/nextSlide()设置clicksDirection.value = 1(见 useNav.ts#L144-L168)prev()/prevSlide()设置clicksDirection.value = -1(见 useNav.ts#L152-L178)
这里有两个值得注意的实现细节:
- 方向在交互瞬间即被确定。
clicksDirection在用户点击"下一页/上一页"(无论是翻页还是页内 v-click 步进)时被立即赋值,早于路由 URL 更新,因此新进入的元素在首帧就能读到正确的方向类,CSStransition可以从导航开始的那一刻就带上方向相关的延迟。 - 方向值不会被重置为 0。它始终保留"最近一次导航方向",也就是说容器在页面加载后首次前进导航前不携带任何方向类,此后则稳定持有 forward 或 backward 之一。
顺带说明:useNav中还导出一个navDirection(1 为前进、-1 为后退,见 useNav.ts#L43-L46),它由路由号差值计算(next.no - prev.no),主要用于解析幻灯片切换过渡,与容器上的方向类互为补充。
写法一:纯 CSS 选择器
最直接的方式是在幻灯片的 CSS(内联样式块、style.css或主题样式)中直接引用这两个容器类。官方文档给出的标准示例是"仅前进时给 v-click 目标加过渡延迟,后退时立即显示":
/* example: delay on only forward but not backward */ .slidev-nav-go-forward .slidev-vclick-target { transition-delay: 500ms; } .slidev-nav-go-backward .slidev-vclick-target { transition-delay: 0; }.slidev-vclick-target是 Slidev 附加在每一个v-click指令目标元素上的类名(元素隐藏时还会附带.slidev-vclick-hidden,机制详见 docs/guide/animations.md)。仓库的 Cypress 端到端测试也大量依赖这一类名来断言点击动画状态,例如 cypress/e2e/examples/basic.spec.ts,可以佐证它是动画体系中稳定、可预期的钩子类。
由于选择器是"容器类 + 后代类"的普通 CSS,你还可以把范围扩大到任何自定义元素,例如:
/* 前进时标题淡入,后退时无动画 */ .slidev-nav-go-forward .slidev-page h1 { transition: opacity 600ms ease; } .slidev-nav-go-backward .slidev-page h1 { transition: none; }写法二:UnoCSSforward:/backward:变体
为避免在模板里手写复杂选择器,Slidev 在客户端 UnoCSS 配置中注册了两个专用变体。实现位于 packages/client/uno.config.ts:
// Slidev Specific Variants, probably extrat to a preset later variants: [ // `forward:` and `backward:` variant to selectively apply styles based on the direction of the slide // For example, `forward:text-red` will only apply to the slides that are navigated forward variantMatcher('forward', input => ({ prefix: `.slidev-nav-go-forward ${input.prefix}` })), variantMatcher('backward', input => ({ prefix: `.slidev-nav-go-backward ${input.prefix}` })), ],variantMatcher是@unocss/preset-mini提供的工具:当它看到forward:前缀时,会把生成的 CSS 选择器重写为.slidev-nav-go-forward <原选择器>。也就是说forward:delay-300最终等价于.slidev-nav-go-forward .\31\... { transition-delay: 300ms }这类带容器前缀的规则。
得益于这一机制,你在 Markdown 里写任意 UnoCSS 类时都可以加方向前缀,例如官方文档中的对比示例:
<div v-click class="transition delay-300">Element</div> <!-- 前后方向都有 300ms 延迟 --> <div v-click class="transition forward:delay-300">Element</div> <!-- 仅前进时有 300ms 延迟 -->上面第二行中,动画只在前进导航时被延迟,回退时元素立即呈现。变体也可以与 UnoCSS 的变体组、dark:等组合使用,且extractorMdc提取器(同样配置于 uno.config.ts#L63-L65)保证 Markdown 内容中的类名能被完整扫描生成。
需要说明的前提:这份客户端配置会经 packages/slidev/node/setups/unocss.ts 与主题、用户项目中的 UnoCSS 配置合并,因此forward:/backward:在常规 Slidev 幻灯片中开箱即用,无需任何额外配置。
与幻灯片切换过渡(transition)的方向语义对照
Slidev 的方向感知并非只有样式这一个落点,幻灯片切换过渡同样区分前进/后退,理解二者关系有助于避免混淆:
- 容器方向类由
clicksDirection驱动,在交互发生时立即更新,面向"页内元素动画的方向条件化"; - 幻灯片整体过渡由
navDirection驱动,解析逻辑在 packages/client/logic/transition.ts 中:内置的slide-left等过渡会自动展开为slide-left | slide-right这样的"前进 | 后退"双向定义,你也可以在前端 frontmatter 中手写transition: 前进名 | 后退名的管道语法来自定义两个方向的不同过渡; - 当过渡为
view-transition(浏览器原生 View Transition API)时,容器会临时从TransitionGroup切换为普通div(见 SlidesShow.vue#L82-L83 与 packages/client/composables/useViewTransition.ts),但方向类绑定不受影响,forward:/backward:变体依旧生效。
从源码结构看,两套机制共享"前进为正、后退为负"的方向约定,只是作用对象不同:transition管的是两页之间的整体切换动画,而方向类管的是进入/离开过程中元素级 CSS 动画的条件化。
实战建议与适用边界
- 典型场景:不对称入场体验。前进时用
forward:给v-click序列加上transition-delay,让要点逐个从容出现;后退时保持delay-0,让观众快速回到上文。 - 选择器粒度:容器类作用域是"当前幻灯片容器",配合
.slidev-vclick-target、.slidev-page等结构性类名即可精确控制目标范围,不影响全局其他组件。 - 注意初始状态:页面首次加载、尚未发生任何导航时,
clicksDirection为 0,两个类都不存在,因此"默认样式"(无前缀规则)会作为兜底生效——这正是需要为"无延迟"显式写出backward:规则或基础规则的原因。 - 版本前提:该能力自 v0.48.0 引入(见 docs/features/direction-variant.md 的 frontmatter 声明),在更早版本中不存在
forward:/backward:变体,纯 CSS 类名选择器同样不可用。
综上,方向变体是 Slidev 用"一个容器类 + 两个 UnoCSS 变体"极低成本实现的方向条件化样式方案:源码层面只需 useNav.ts 中四处一行赋值、SlidesShow.vue 中的 class 绑定,以及 uno.config.ts 中两个variantMatcher注册,用户侧则可以在 Markdown 单行 class 或 CSS 文件中自由发挥。
【免费下载链接】slidevPresentation Slides for Developers项目地址: https://gitcode.com/GitHub_Trending/sl/slidev
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考