vue进入/离开 & 列表过渡transition
一.transition过渡
1.需求1(优化):想要一种效果,想要ios那种页面切换效果,总而言之就是过渡效果。
附上官网介绍地址:https://cn.vuejs.org/v2/guide/transitions.html
1.
App.vue代码片段如下:
<template> <div id="app"> <transition :name="transitionName"> <keep-alive> <router-view v-if="$route.meta.keepAlive"></router-view> </keep-alive> </transition> <transition :name="transitionName"> <router-view v-if="!$route.meta.keepAlive"></router-view> </transition> </div> </template>
以上是HTML上的代码,在keep-alive外层,增加transition,并且绑定name属性transitionName(这个是一个变量,用来控制想要加的样式前缀),看了下面的代码你就懂了:
watch: {//使用watch 监听$router的变化 $route(to, from) { //如果to索引大于from索引,判断为前进状态,反之则为后退状态 if(to.meta.index > from.meta.index){ //设置动画名称 this.transitionName = 'slide-left'; }else{ this.transitionName = 'slide-right'; } } }
import Vue from 'vue'; import VueRouter from 'vue-router' import Home from '@V/home' import List from '@V/list' import Approve from '@V/approve' import DetailInfo from '@V/detailInfo' import Info from '@V/info' Vue.use(VueRouter) export const routes = [ { path:'/', name:'home', component:Home, meta: { keepAlive: false, index:1 }, }, { path:'/list', name:'list', component:List, meta: { keepAlive: true, index:2 }, }, { path:'/approve', name:'approve', component:Approve, meta: { keepAlive: false, index:3 }, }, { path:'/detailInfo', name:'detailInfo', component:DetailInfo, meta: { keepAlive: false, index:3 }, }, { path:'/info', name:'info', component:Info, meta: { keepAlive: false, index:4 }, } ]
看到这里估计你仅仅是知道transition变量是根据页面切换to和from索引来控制值,其实这个值是一个过渡类名的前缀,用来拼接transition的过渡状态,以下引用官方的解释:
过渡的类名
在进入/离开的过渡中,会有 6 个 class 切换。
-
v-enter
:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。 -
v-enter-active
:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。 -
v-enter-to
: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时v-enter
被移除),在过渡/动画完成之后移除。 -
v-leave
: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。 -
v-leave-active
:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。 -
v-leave-to
: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时v-leave
被删除),在过渡/动画完成之后移除。
对于这些在过渡中切换的类名来说,如果你使用一个没有名字的 <transition>
,则 v-
是这些类名的默认前缀。如果你使用了 <transition name="my-transition">
,那么 v-enter
会替换为 my-transition-enter
。
以上是官方的解释,下面看看css是怎么写的:
.slide-right-enter-active, .slide-right-leave-active, .slide-left-enter-active, .slide-left-leave-active { will-change: transform; transition: all 500ms; position: absolute; } .slide-right-enter { opacity: 0; transform: translate3d(-100%, 0, 0); } .slide-right-leave-active { opacity: 0; transform: translate3d(100%, 0, 0); } .slide-left-enter { opacity: 0; transform: translate3d(100%, 0, 0); } .slide-left-leave-active { opacity: 0; transform: translate3d(-100%, 0, 0); }
以上就是把transition的状态写了个过渡样式,加上这样的代码,你就可以实现需求一。附上完整代码:
<template> <div id="app"> <transition :name="transitionName"> <keep-alive> <router-view v-if="$route.meta.keepAlive"></router-view> </keep-alive> </transition> <transition :name="transitionName"> <router-view v-if="!$route.meta.keepAlive"></router-view> </transition> </div> </template> <script> export default { name: 'app', data(){ return { // text:sessionStorage.getItem('parameters') transitionName:'' } }, watch: {//使用watch 监听$router的变化 $route(to, from) { //如果to索引大于from索引,判断为前进状态,反之则为后退状态 if(to.meta.index > from.meta.index){ //设置动画名称 this.transitionName = 'slide-left'; }else{ this.transitionName = 'slide-right'; } } } } </script> <style lang="less"> @import '~vux/src/styles/reset.less'; #app{ /*position: relative;*/ } body { background-color: #fbf9fe; } .vux-x-icon { fill:#1d83ef; } .backicon { width:38px; height:38px; display:inline-block; border-radius:100%; border:1px solid #1d83ef; } .slide-right-enter-active, .slide-right-leave-active, .slide-left-enter-active, .slide-left-leave-active { will-change: transform; transition: all 500ms; position: absolute; } .slide-right-enter { opacity: 0; transform: translate3d(-100%, 0, 0); } .slide-right-leave-active { opacity: 0; transform: translate3d(100%, 0, 0); } .slide-left-enter { opacity: 0; transform: translate3d(100%, 0, 0); } .slide-left-leave-active { opacity: 0; transform: translate3d(-100%, 0, 0); } </style>
注明:上周5同事发现了一个bug,发现用transition之后,切换页面的时候可能可能可能会出现一个问题:会出现短暂的白板!!!同事说,可能是加了transition左右滑动的时候定位出现的问题,所以出现短暂白板。当时的解决方案就是,在app.vue中的,给#app加了个样式,position:relative,其他的子组件每个最外层都加了个position:absolute。这样就完美解决了。不过今天写博客的时候,我又实验了一把,没出现白板的问题。如果出现以上问题,就试试加个定位吧。
另外,还有个bug,上面的代码,是通过v-if去判断缓存,而且有两个transition,运行起来发现,切换页面的时候交替闪现,其实,这里也猜到了,是两个transition通过v-if判断的时候,出现的交错的bug。下面继续完善上面的需求:
下面是文档介绍:
include - 字符串或正则表达式。只有匹配的组件会被缓存。
exclude - 字符串或正则表达式。任何匹配的组件都不会被缓存。
下面贴上更改后app.vue的代码:
<template> <div id="app"> <transition :name="transitionName"> <keep-alive include="list"> <router-view></router-view> <!--<router-view v-if="$route.meta.keepAlive"></router-view>--> </keep-alive> </transition> <!--<transition :name="transitionName"> <router-view v-if="!$route.meta.keepAlive"></router-view> </transition>--> </div> </template>
app.vue其他地方不变,这里引入的include(当然,如果你喜欢用exclude也可以,相反而已,排除引号内的组件名字,以外的都要缓存)是要缓存的组件name,多个缓存页面name用逗号分隔。比如:include="list,info,home"
所以路由页面的页不用设置meta:{keepAlive:true}了,路由代码如下:
export const routes = [ { path:'/', name:'home', component:Home, meta: { index:1 }, }, { path:'/list', name:'list', component:List, meta: { index:2 }, }, { path:'/approve', name:'approve', component:Approve, meta: { index:3 }, }, { path:'/detailInfo', name:'detailInfo', component:DetailInfo, meta: { index:3 }, }, { path:'/info', name:'info', component:Info, meta: { index:4 }, } ]
over,这是今天的内容,自己的一份记录,也希望对你有帮助。