前言:在vue中切换页面路由时是没有任何动画效果的,所以到网上找了下如何实现类似于原生App那样的左右滑动动画,总结了下大致有几种方法,各有优缺点。
一. 在vue-router原型上挂载goBack方法
这个方法网上是最多的,但是我试了并没有生效,先记录下来吧
1.首先在router文件夹下的index.js中定义goBack方法
import Router from 'vue-router'
Vue.use(Router)
Router.prototype.goBack = function () {
this.isBack = true //判断是否是返回操作
window.history.go(-1)
}
复制代码
2.在App.vue中动态绑定路由动画
<transition :name="transitionName">
<router-view class="child-view"></router-view>
</transition>
//在路由发生变化时监听是前进还是后退状态,应用不同动画
watch: {
'$route' (to, from){
let isBack = this.$router.isBack;
if(isBack) {
this.transitionName = 'slide-right'
} else {
this.transitionName = 'slide-left'
}
this.$router.isBack = false
}
}
复制代码
3.前进后退动画
.child-view {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
}
.slide-left-enter,
.slide-right-leave-active {
opacity: 0;
-webkit-transform: translate(50px, 0);
transform: translate(50px, 0);
}
.slide-left-leave-active,
.slide-right-enter {
opacity: 0;
-webkit-transform: translate(-50px, 0);
transform: translate(-50px, 0);
}
复制代码
4.在需要后退动画的路由上调用goBack方法
this.$router.goBack()
复制代码
最后,不知道是不是调用有问题,一直不生效,也没找到是什么原因。以后如果解决了这个问题再来补充。下面来说第二种方法,这个效果是实现了的,相对来说也比较简单。
二. 在路由中使用meta对象定义当前层级
1.在路由配置中加一个meta对象,index代表当前路由的层级,由高层级跳转到底层级则视为返回,相反视为前进。
export default new Router({
routes: [{
path: '/',
name: 'Home',
meta:{index:0},
component: Home
},
{
path: '/category',
name: 'Category',
meta:{index:1},
component: Category
},
{
path: '/shopcart',
name: 'Shopcart',
meta:{index:2},
component: Shopcart
}
]
})
复制代码
2.设置路由动画,与第一种方法相同
3.监听路由变化,比较层级索引,如果to索引大于from索引,判断为前进状态,反之则为后退状态
watch: {
'$route'(to, from) {
if(to.meta.index > from.meta.index){
this.transitionName = 'slide-left';
}else{
this.transitionName = 'slide-right';
}
}
}
复制代码
4.设置前进后退动画,也与第一种方法相同
这样,就可以自己定义层级,实现动态切换路由动画效果啦。
三. 使用vuex,给路由增加索引存到seesionStorage中
据说这个是由移动端框架vux的源码改编的
1.App.vue中给路由添加动画效果
<transition :name="'vux-pop-' + (direction === 'forward' ? 'in' : 'out')">
<keep-alive>
<router-view class="router-view" ></router-view>
</keep-alive>
</transition>
复制代码
用vuex存储状态
import { mapState } from 'vuex'
computed:{
...mapState({
direction: state => state.mutations.direction
})
}
复制代码
设置转场动画样式
<style scoped>
.vux-pop-out-enter-active,
.vux-pop-out-leave-active,
.vux-pop-in-enter-active,
.vux-pop-in-leave-active {
will-change: transform;
transition: all 250ms;
height: 100%;
top: 0;
position: absolute;
backface-visibility: hidden;
perspective: 1000;
}
.vux-pop-out-enter {
opacity: 0;
transform: translate3d(-100%, 0, 0);
}
.vux-pop-out-leave-active {
opacity: 0;
transform: translate3d(100%, 0, 0);
}
.vux-pop-in-enter {
opacity: 0;
transform: translate3d(100%, 0, 0);
}
.vux-pop-in-leave-active {
opacity: 0;
transform: translate3d(-100%, 0, 0);
}
</style>
复制代码
在main.js中给路由增加索引,存到sessionStorage里,以点击过的索引值不变,新增加的路由,索引增加1,同时count+1,这样在页面切换时通过比较索引值的大小,大的向右小的向左,做到左右有规律的过渡。
const history = window.sessionStorage;
history.clear()
let historyCount = history.getItem('count') * 1 || 0;
history.setItem('/', 0);
router.beforeEach(function (to, from, next) {
const toIndex = history.getItem(to.path);
const fromIndex = history.getItem(from.path);
if (toIndex) {
if (!fromIndex || parseInt(toIndex, 10) > parseInt(fromIndex, 10) || (toIndex === '0' && fromIndex === '0')) {
store.commit('UPDATE_DIRECTION', {direction: 'forward'})
} else {
store.commit('UPDATE_DIRECTION', {direction: 'reverse'})
}
} else {
++historyCount;
history.setItem('count', historyCount);
to.path !== '/' && history.setItem(to.path, historyCount);
store.commit('UPDATE_DIRECTION', {direction: 'forward'})
}
next()
});
复制代码
store/mutation.js
const state = {
direction: 'forward',
};
复制代码
所有评论(0)