【山竹记账前端-vue】5.动画、SVG Sprites 与滑动手势
大纲链接 §
[toc]
0. 展示 git 操作,切换代码版本 ⇧
拿到代码地址:https://github.com/FrankFang/vue-mangosteen/tree/1008fb833e235f9f8c86ca84277de993ca3162bd
- 下载 初始代码
可以先 fork 一份到自己的仓库再操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30# 1. 克隆整个仓库到本地 4d7b4c 文件夹 git clone https://github.com/FrankFang/vue-mangosteen.git 4d7b4c # 2. 进入进入克隆下来的项目目录 cd 4d7b4c # 3. 切换到指定的 Commit ID 65cd653 完成欢迎界面动画 git checkout 65cd65383adbc34368bc5b75e0ee3e96bbedceac # 4。 打印最近几条提交记录 按上下箭头翻页;按q退出 git log # 5. 找到 完成欢迎界面动画 提交哈希 65cd65,在终端中展示提交内容 git show 65cd6 # 6. commit 变补丁: generate a git patch from a commit git format-patch -1 65cd6 # 0001-.patch 可以看到多了一个文件 0001-.patch ls -a # 移动到最初代码的克隆仓库 mv 0001-.patch ../magosteen-fe-3 cd ../magosteen-fe-3 # 重置不需要提交的更改 git state git reset --hard HEAD # 将补丁应用到最初代码的克隆仓库 git am < 0001-.patch #Applying: 完成欢迎界面动画 # 删除多余补丁文件 rm -rf 0001-.patchgit show HEAD显示最新一次提交的内容git diff展示当前没有提交的变动内容
多重 RouterView(命名视图) 与 Transition 实现
1. 插槽函数改写 RouterView ⇧
SFC写法
|
|
使用插槽函数改写
@/views/WelcomeView.tsx
|
|
<component :is="Component" />相当于{ (option: any) => h(option.Component) }- 通过
h(option.Component)来渲染 - 还可以写成
{ (option: any) => <option.Component/> } option.Component的类型即为VNode- 当然还可以用标签包裹
{ (option: any) => <div class="frank"><option.Component/><div> } - 换成
trasition即{ (option: any) => <transition class="frank"><option.Component/><transition> }
- 通过
点击进入查看
RouterView的类型,看到默认插槽函数的参数类型,可解构出插槽组件Component和route(待用)1 2 3 4 5 6 7 8 9 10 11declare const RouterView: { new (): { $props: AllowedComponentProps & ComponentCustomProps & VNodeProps & RouterViewProps; $slots: { default?: ({ Component, route }: { Component: VNode; route: RouteLocationNormalizedLoaded; }) => VNode[]; }; }; };
重构一下写法
@/views/WelcomeView.tsx
|
|
- 解构默认插槽组件和路由信息
({Component, route}) => () - 声明类型
({Component, route}: {Component: VNode, route: RouteLocationNormalizedLoaded}) => () - 在
TSX中无法使用内置组件<component>,将Component作为is属性传入,并且必须在标签形式上绑定key- 即
<component is={Component} key={route.path} />❌
- 即
Vue Router 4/5在<RouterView>插槽中通过Component参数传递出来的并不是组件类/函数,而是已经实例化的虚拟节点对象 (VNode)- 当执行
<Component />即h(Component)时,实际上是在把一个VNode对象当作组件类型传给h()创建新的VNode - 这会导致 Vue 运行时无法正确解析组件生命周期和属性,可能触发控制台警告、路由过渡动画失效或渲染异常
- 后果:Vue 运行时会报错(例如渲染出
[object Object]或者白屏), - 或者每次路由切换时,整个组件树都会被强行销毁并完全重新创建,导致页面状态丢失、生命周期重复触发等严重的运行时 Bug
- 当执行
- 可转而使用
cloneVNodeComponent本身已经是一个完整的、包含了组件实例信息的VNode- 想为它动态注入、克隆或者修改属性(比如绑定
key或者是传递给<Transition>时的特殊属性),Vue官方提供的标准API就是cloneVNode
- 当未来需要配合
<Transition>(路由动画) 或<KeepAlive>(路由缓存) 使用时,cloneVNode是TSX语法下的唯一完美解法- 因为
Vue的<Transition>要求内部必须是一个直接的、连续的VNode节点
- 功能完备:
cloneVNode能够精确地为已有虚拟节点附加key属性,确保路由在不同参数或子路径切换时正确触发重渲染与动画
收益与代价权衡
| 方案 | 编译期表现 | 运行时安全性 | 列维护成本与系统效用2 |
|---|---|---|---|
行伪造签名 + <Component /> |
无报错(虚假安全) | 存在风险(VNode 二次包装) | 低效用:增加了隐性 Bug 排查成本,违背运行时真实数据结构 |
| 标准 cloneVNode 方案 | 完全类型安全 | 100% 正确(官方推荐) | 高效用:消除歧义,保障路由切换与过渡效果的最高稳定性 |
参考
使用 Vue Router 命名视图,改写路由 ⇧
@/router/routes.ts
|
|
components: { main: Welcome1stPage }- 可以对应多重
RouterView<RouterView name="main">
@/views/WelcomeView.tsx
|
|
路由切换main部分添加Transition ⇧
原
SFC内置过渡组件
|
|
注意引入内置组件大驼峰形式
import { Transition } from 'vue':@/views/WelcomeView.tsx
|
|
引入动画样式
@/modules/welcome/WelcomeView.module.scss
|
|
- 暂时使用全局样式
- 内置组件设置了名称
<Transition name="fade">,标记动画样式前缀- 添加四个动画类名
.fade-enter-active、.fade-leave-active、.fade-enter-from、.fade-leave-to、
- 添加四个动画类名
- 过渡动画样式设置成功,但不是左右滑动的样式
修改自定义动画
|
|
修改样式
@/modules/welcome/WelcomeView.module.scss
|
|
- 延长时间查看效果
main容器下同时出现两个卡片内容,元素位置互不影响需要使用定位样式:main使用相对定位- 内容元素使用绝对定位
修改样式
@/modules/welcome/WelcomeView.module.scss
|
|
- 从右侧距离一个屏幕宽度的地方进入
.slide-fade-enter-from { transform: translateX(100vw); } - 从左侧距离一个屏幕宽度的地方移出
.slide-fade-leave-to { transform: translateX(-100vw); } - 合并正在进入和离开时的过渡样式
@/views/WelcomeView.tsx
|
|
- 注意
Transition里包裹的元素必须有根节点,添加一层 div - 将部分定位相关样式和
key属性都放到这个节点上
回顾过渡动画过程
- 需要让
RouterView里面 使用Transition包住Component - 在
Transition给动画去一个名称slide-fade,作为动画类样式前缀 - 补充四个过渡类样式
参考
使用 CSS Module 改写 :global 全局动画 ⇧
防止重名的动画类样式
Ctrl + B查看Transition的参数声明
|
|
- 可以使用额外的动画钩子属性
enterActiveClassleaveActiveClassenterFromClassleaveToClass
- 使用
CSS Module的类样式传入这些动画钩子属性
@/modules/welcome/WelcomeView.module.scss
|
|
@/views/WelcomeView.tsx
|
|
- 目前只做到了前进方向的动画,后退暂时不做
- 思路是可以根据解构出来的
route信息添加判断来动态引入不同的模块样式来做
- 思路是可以根据解构出来的
总结路由与动画
- 重构路由结构,使用
vue-router高级功能 命名视图<RouterView name="main">{/* ... */}</RouterView>
vue内置组建在TSX中都为大驼峰写法引入import { Transition} from 'vue'TSX中插槽为函数,将SFC写法转为TSX写法- 解构出插槽组件
Component,放到Trasition组件中
- 解构出插槽组件
- 将动画部分放入
<Transition name="slide_fade">{Component}</Transition>- 在
Transition上添加模块化类样式 enterFromClass={s.slide_fade_enter_from}enterActiveClass={s.slide_fade_enter_active}leaveToClass={s.slide_fade_leave_to}leaveActiveClass={s.slide_fade_leave_active}>
- 在
还原之前的四个欢迎页面,不使用插槽写法 ⇧
- 去除使用插槽的
WelcomeLayout.tsx
@/modules/welcome/WelcomePage.module.scss
|
|
@/modules/welcome/Welcome1stPage.tsx
|
|
存在的问题:
- 图标第一次加载不流畅
- 加载多个图标,发起多个资源请求
下一章处理:
Vite SVG Sprites
参考文章
相关文章
- 作者: Joel
- 文章链接:
- 版权声明
- 非自由转载-非商用-非衍生-保持署名