前言:在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',
};
复制代码

原文链接:www.jianshu.com/p/a29d5ecfa…

转载于:https://juejin.im/post/5bbef2e16fb9a05cdc49ab4b

Logo

前往低代码交流专区

更多推荐