前沿
昨天在bilibili 上看见了AnthonyFu一个托尼大佬的视频,起飞!跨路由 Vue 组件动画实验,关于如何去实现路由之间的组件共享,并且有一个十分平滑的动画。Vue-StarPort这是AnthonyFu一个托尼开源发布的一个Demo。有兴趣的朋友们可以去看一看。
在 Flutter 中,有一个Hero组件,可以实现路由间的组件动画,并且十分的平滑。但是在 Web 中似乎没有那么好的实现,幸好 Vue 为我们提供了一个Teleport组件。
有一个FLIP动画思想,大家不了解的话,可以去其他的帖子上面看一看,一个简单却很实用的东西。
出现的问题
当从A跳转到B的时候,A组件会被销毁,B组件会被创建。我们希望在A跳转到B的时候,A中的Share不被销毁,而B中的Share不会被创建,而是沿用A中的Share。
这就涉及到如何去保存组件的状态并且将在页面之间移动
实现
这张图来自
AnthonyFu一个托尼
我的实现是比较笨重的,大概就是将这个共享的组件挂载到全局,并记录下这个组件的信息(位置),监听路由的变化,并且在通过Teleport包裹,每次更换页面时候动态的为它更换位置和动画。
Code
- 将组件挂在到全局,后面进入组件的时候再加上去
const app = createApp(App)
app.config.globalProperties.$animateEl = {
el: null, // 组件
pos: ref("#app"), // 挂载的位置 有三种状态 悬空在#app 起点 落点
posEnable: ref(true), // 是否移动
reset() { // 重置状态 ,如果需要按钮控制,这个就有用
this.el!.style.animation = "ThroughBack .5s ease-in-out forwards"
this.posEnable.value = true
this.pos.value = "#app"
}, // 如果动画满足不了需求,就使用定位做动画
setTo(x: number, y: number) {
this.afterLeft = x
this.afterTop = y
}, // 重置位置
initAnimate() {
this.el!.style.cssText = `
transform:translate(${this.top}px,${this.left}px) scale(1)
`
}
}
- 新建一个
StarPort 组件
其中的pos用于控制应该把这个组件移动到哪里去,posEnable控制是否禁用,在第一次的时候我们希望他保持在原地,在产生了路由跳转之后在移动。revise为这个组件添加了一个事件,点击组件就可以跳到另外一个页面,再点击就会跳回来。在这个过程中我们为他添加了一个动画,让他看起来更平滑
<Teleport :to="pos" :disabled="posEnable">
<div @click.stop="revise" ref="runImg" class="animationImg" style="transition: all .3s ease-in-out;">
<slot />
</div>
</Teleport>
用法
想要体验的小伙伴可以试一试
写了一个十分简单的动画,有兴趣的伙伴可以重写动画 ,他们分别是ThroughGo和ThroughBack,代表着进入路由的动画和离开路由的动画
npm install starport-vue@1.0.3 仅支持单组件
npm install starport-vue@1.0.4 支持多组件
- 在入口文件中引入
如果有小伙伴使用了ts,需要新建一个.d.ts声明一下
import StarPort from "starport-vue"
import "starport-vue/style.css"
app.use(StarPort)
- 在组件中使用
<div>
<StarPort end-el=".aboutWrapper" end="/about" start="/home">
组件
</StarPotr>
</div>
| 参数 | 说明 | 类型 |
|---|---|---|
| end | 到达的路由 | string |
| endEl | 到达的元素,是一个选择器,标签、类、id选择器都可以 | string |
| start | 开始的路由 | string |
总结
这个实现显然不是最优的方法,如果需要做一个列表,那花费将有点大。如果有伙伴有更好的想法,欢迎评论