美文网首页
[vue-router4进阶] 0.过渡动效

[vue-router4进阶] 0.过渡动效

作者: 林哥学前端 | 来源:发表于2021-11-01 15:22 被阅读0次

    现在我们开始学习一些vue-router的高级一点的内容,这节课我们一起学习如何在页面跳转时添加一些过渡动效。
    我们还是继续在vue-router4快速入门的例子的基础上改,先把之前的嵌套路由的代码去掉,就剩下一个简单的首页、列表页和用户详情页。
    添加过渡效果需要用到vue自带的内置组件transition,transition组件的作用就是在它的里面的内容发生变化时,增加过渡效果,具体用法在这里
    给页面跳转增加过渡效果的方式跟之前的版本区别比较大,这里要在router-view上使用v-slot获取对应的组件,使用component动态组件来渲染这个组件,然后用transition包裹住这个动态组件:

    <router-view v-slot="{ Component }">
      <transition name="fade">
        <component :is="Component" />
      </transition>
    </router-view>
    

    这样在页面切换时,动态组件的内容发生了变化,这里我们定义了一个名字是fade的transition,就会有一个fade的过渡效果了,不过我们需要用css定义这个fade效果:

    .fade-enter-active {
      transition: opacity 0.5s ease;
    }
    .fade-leave-active {
      transition: none;
    }
    .fade-enter-from,
    .fade-leave-to {
      opacity: 0;
    }
    

    transition大概就是这样一个用法,这里定义的过渡时,如果组件离开页面,就直接消失,如果组件进入页面就有个0.5秒的透明度动画。
    这么写好以后,点击跳转页面,发现并没有效果。原来,使用transition时,页面的vue文件的template下必须只有一个根元素
    比如index.vue应该是:

    <template>
      <div class="page">
        <div>这里是首页</div>
        <router-link to="/list">点击跳转到列表页</router-link>
      </div>
    </template>
    

    只有一个根div,这样改完之后就有淡入的fade效果了。
    为了效果更好一点,让每个页面都全屏大小,定位在顶部。
    添加一个class,叫page

    .page {
      position: absolute;
      width: 100%;
      height: 100vh;
      left: 0;
      top: 0;
    }
    

    每个页面的根元素上都加上这个class,淡入的效果就完成了。

    淡入的效果还是不太好看,下面按照官网的例子,做一个进入下层页面从右边滑过来、进入上层页面从左边滑过来的例子,
    这时候,transition的效果是动态的,一共两个,slide-left和slide-right,我们在route配置时候的meta里增加一个属性,表示transition的效果,默认是slide-left
    router.js

      {
        path: '/index',
        component: () => import('./views/index'),
        name: 'index',
        meta: {
          title: '首页',
          keepAlive: true,
          transition: 'slide-left',  // 增加
        },
      },
    

    然后在App.vue里面,动态设置transition的name属性:

        <router-view v-slot="{ Component, route }">
          <transition :name="route.meta.transition"> // name是动态绑定的
            <component :is="Component" />
          </transition>
        </router-view>
    

    在router.js中增加导航守卫,动态的更改route里面meta的transition的值:

    router.afterEach((to, from) => {
      // 新增
      const toDepth = to.path.split('/').length
      const fromDepth = from.path.split('/').length
      to.meta.transition = toDepth < fromDepth ? 'slide-right' : 'slide-left'
    })
    
    

    这样过渡的效果就是动态的了,在slide-left和slide-right之间变化,
    最后在加上效果的css代码:

    .slide-left-enter-active {
      transition: transform 0.5s ease;
    }
    .slide-left-leave-active {
      transition: none;
    }
    .slide-left-enter-from,
    .slide-left-leave-to {
      transform: translate3d(100vw, 0, 0);
    }
    .slide-right-enter-active {
      transition: transform 0.5s ease;
    }
    .slide-right-leave-active {
      transition: none;
    }
    .slide-right-enter-from,
    .slide-right-leave-to {
      transform: translate3d(-100vw, 0, 0);
    }
    

    这就完成了,
    最后效果就是进入用户详情页,页面时从右边滑过来,从用户详情页返回,页面是从左边滑过来。
    下面把整个项目的代码贴出来
    App.vue

    <template>
      <div>
        <router-view v-slot="{ Component, route }">
          <transition :name="route.meta.transition">
            <component :is="Component" />
          </transition>
        </router-view>
      </div>
    </template>
    
    <script>
    export default {
      name: 'App',
    }
    </script>
    
    <style>
    .slide-left-enter-active {
      transition: transform 0.5s ease;
    }
    .slide-left-leave-active {
      transition: none;
    }
    .slide-left-enter-from,
    .slide-left-leave-to {
      transform: translate3d(100vw, 0, 0);
    }
    .slide-right-enter-active {
      transition: transform 0.5s ease;
    }
    .slide-right-leave-active {
      transition: none;
    }
    .slide-right-enter-from,
    .slide-right-leave-to {
      transform: translate3d(-100vw, 0, 0);
    }
    .page {
      position: absolute;
      width: 100%;
      height: 100vh;
      left: 0;
      top: 0;
    }
    </style>
    
    

    router.js

    import { createRouter, createWebHistory } from 'vue-router'
    
    const routes = [
      {
        path: '/index',
        component: () => import('./views/index'),
        name: 'index',
        meta: {
          title: '首页',
          keepAlive: true,
          transition: 'slide-left', // 新增
        },
      },
      {
        path: '/list',
        component: () => import('./views/list'),
        name: 'list',
        meta: {
          title: '用户列表',
          keepAlive: true,
          transition: 'slide-left', // 新增
        },
      },
      {
        path: '/userDetail/:id',
        component: () => import('./views/userDetail'),
        name: 'userDetail',
        meta: {
          title: '用户详情',
          keepAlive: true,
          transition: 'slide-left', // 新增
        },
      },
    ]
    
    const router = createRouter({
      history: createWebHistory(),
      routes,
    })
    
    router.afterEach((to, from) => {
      // 新增
      const toDepth = to.path.split('/').length
      const fromDepth = from.path.split('/').length
      to.meta.transition = toDepth < fromDepth ? 'slide-right' : 'slide-left'
    })
    
    export default router
    
    

    index.vue

    <template>
      <div class="page">
        <div>这里是首页</div>
        <router-link to="/list">点击跳转到列表页</router-link>
      </div>
    </template>
    
    <script>
    export default {}
    </script>
    
    <style></style>
    
    

    list.vue

    <template>
      <div class="page">
        <div>这里是列表页</div>
        <router-link to="/index">点击跳转到首页</router-link>
        <ul>
          <li v-for="item in userList" :key="item.id">
            <router-link
              :to="{
                name: 'userDetail',
                params: {
                  id: item.id,
                },
                query: {
                  name: item.name,
                },
              }"
              >点击查看{{ item.name }}</router-link
            >
          </li>
        </ul>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          userList: [
            {
              name: '亚历山大',
              id: '01',
            },
            {
              name: '凯撒',
              id: '02',
            },
            {
              name: '屋大维',
              id: '03',
            },
          ],
        }
      },
    }
    </script>
    
    <style></style>
    
    

    userDetail.vue

    <template>
      <div class="page">用户详情页获取到了id:{{ id }},他的名字是:{{ name }}</div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          id: '',
          name: '',
        }
      },
      mounted() {
        this.id = this.$route.params.id
        this.name = this.$route.query.name
      },
    }
    </script>
    
    <style></style>
    
    

    相关文章

      网友评论

          本文标题:[vue-router4进阶] 0.过渡动效

          本文链接:https://www.haomeiwen.com/subject/uhszaltx.html