Featured image of post Vue3 切换路由动画效果 2023

Vue3 切换路由动画效果 2023

2023-02-17-vue_router_transition.gif

定义路由

import {
  createRouter,
  createWebHashHistory,
  createWebHistory,
} from "vue-router";
import routes from "./root";

// 导入生成的路由数据
const router = createRouter({
  history: createWebHistory(),
  routes,
});

export default router;
// src/router/root.ts
import type { RouteRecordRaw } from "vue-router";

export default [
  {
    path: "/",
    name: "Home",
    // 别名
    alias: "/home",
    component: () => import("@/views/Home/index.vue"),
  },
  {
    path: "/demo",
    name: "Demo",
    component: () => import("@/views/Demo/index.vue"),
  },
  {
    path: "/demo2",
    name: "Demo2",
    component: () => import("@/views/Demo2/index.vue"),
  },
  {
    path: "/study",
    name: "Study",
    component: () => import("@/views/Study/index.vue"),
  },
] as RouteRecordRaw[];

定义结构

  • routerTransition 变量有什么用?
    • 不懂?我们往下看
<template>
  <div class="app">
    <div class="router">
      <div class="content">
        <div class="router-list">
          <router-link
            v-for="item in routerList"
            :key="item.url"
            :to="item.url"
            class="link-a"
          >
            {{ item.name }}
          </router-link>
        </div>

        <div class="router-content">
          <router-view v-slot="{ Component }">
            <transition :name="routerTransition">
              <component :is="Component"></component>
            </transition>
          </router-view>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { ref, reactive } from "vue";
  import { useRouter } from "vue-router";

  let router = useRouter();

  // 判断动画的动作
  let routerTransition = ref("fade_router-default");

  const routerList = reactive([
    {
      url: "/",
      name: "Home",
    },
    {
      url: "/demo",
      name: "Demo",
    },
    {
      url: "/demo2",
      name: "Demo2",
    },
    {
      url: "/study",
      name: "Study",
    },
  ]);
</script>

关键代码

  • routerTransition 当值为 fade_router-right 时表示,动画应为从右到左进行
router.beforeEach((to, from, next) => {
  let toIndex = routerList.findIndex((item) => item.url === to.path);
  let fromIndex = routerList.findIndex((item) => item.url === from.path);

  // 在下面 css 那有相关解释. 想看自行跳转.
  if (toIndex > fromIndex) {
    routerTransition.value = "fade_router-right";
  } else {
    routerTransition.value = "fade_router-left";
  }

  next();
});
// 默认
.fade_router-default-enter-active,
.fade_router-default-leave-active {
  transition: all 0;
}
.fade_router-default-enter {
  opacity: 0;
}
.fade_router-default-enter {
  opacity: 0;
}

// 简单说两句
// 我们拿 fade_router-right 过来举例子
// 1. 新元素需要从 "右边" 进来, 故 v-enter-from 使元素在 "右边出现" .
// 2. 旧元素需要移动到 "左边" , 故 v-leave-to 使元素的 "目的地" 是左边.
.fade_router-right-enter-from,
.fade_router-left-leave-to {
  transform: translate(100%, 0);
}

.fade_router-right-leave-to,
.fade_router-left-enter-from {
  transform: translate(-100%, 0);
}

.fade_router-left-leave-active,
.fade_router-right-leave-active,
.fade_router-left-enter-active,
.fade_router-right-enter-active {
  transition: all 0.5s ease-out;
}

完整代码

<template>
  <div class="app">
    <div class="router">
      <div class="content">
        <div class="router-list">
          <router-link
            v-for="item in routerList"
            :key="item.url"
            :to="item.url"
            class="link-a"
          >
            {{ item.name }}
          </router-link>
        </div>

        <div class="router-content">
          <router-view v-slot="{ Component }">
            <transition :name="routerTransition">
              <component :is="Component"></component>
            </transition>
          </router-view>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { ref, reactive } from "vue";
  import { useRouter } from "vue-router";

  let router = useRouter();

  let routerTransition = ref("fade_router-default");

  const routerList = reactive([
    {
      url: "/",
      name: "Home",
    },
    {
      url: "/demo",
      name: "Demo",
    },
    {
      url: "/demo2",
      name: "Demo2",
    },
    {
      url: "/study",
      name: "Study",
    },
  ]);

  router.beforeEach((to, from, next) => {
    let toIndex = routerList.findIndex((item) => item.url === to.path);
    let fromIndex = routerList.findIndex((item) => item.url === from.path);

    // 在下面 css 那有相关解释. 想看自行跳转.
    if (toIndex > fromIndex) {
      routerTransition.value = "fade_router-right";
    } else {
      routerTransition.value = "fade_router-left";
    }

    next();
  });
</script>

<style lang="scss">
  .app {
    * {
      margin: 0px;
      padding: 0px;
      box-sizing: border-box;
    }

    li {
      list-style: none;
    }

    a {
      text-decoration: none;
    }

    select,
    input,
    label,
    button {
      vertical-align: middle;
    }

    .router {
      position: relative;
      width: 40rem;
      height: max-content;
      margin: 0 auto;
      margin-top: 2rem;

      border-radius: 2rem;
      overflow: hidden;

      &::before {
        position: absolute;
        display: block;
        content: "";
        width: 100%;
        height: 100%;
        background-color: #c5c6b620;

        z-index: 5;
      }

      > .content {
        position: relative;
        z-index: 20;
        padding: 2rem;
      }

      .router-list {
        display: flex;
        justify-content: center;
        flex-wrap: warp;
        column-gap: 20px;

        .link-a {
          color: #ee7785;
          font-size: 1.5rem;

          opacity: 0.4;

          transition: all 0.3s;

          &.router-link-active {
            opacity: 1;
          }
        }
      }

      .router-content {
        width: 100%;
        margin-top: 2rem;

        > div {
          display: flex;
          flex-direction: column;
          align-items: center;
        }

        // 默认
        .fade_router-default-enter-active,
        .fade_router-default-leave-active {
          transition: all 0;
        }
        .fade_router-default-enter {
          opacity: 0;
        }
        .fade_router-default-enter {
          opacity: 0;
        }

        // 简单说两句
        // 我们拿 fade_router-right 过来举例子
        // 1. 新元素需要从 "右边" 进来, 故 v-enter-from 使元素在 "右边出现" .
        // 2. 旧元素需要移动到 "左边" , 故 v-leave-to 使元素的 "目的地" 是左边.
        .fade_router-right-enter-from,
        .fade_router-left-leave-to {
          transform: translate(100%, 0);
        }

        .fade_router-right-leave-to,
        .fade_router-left-enter-from {
          transform: translate(-100%, 0);
        }

        .fade_router-left-leave-active,
        .fade_router-right-leave-active,
        .fade_router-left-enter-active,
        .fade_router-right-enter-active {
          transition: all 0.5s ease-out;
        }
      }
    }
  }
</style>
Licensed under CC BY-NC-SA 4.0
本博客已稳定运行
发表了53篇文章 · 总计28.17k字
使用 Hugo 构建
主题 StackJimmy 设计