网站LOGO
白雾茫茫丶
页面加载中
11月8日
网站LOGO 白雾茫茫丶
记录学习、生活和有趣的事
菜单
  • 热评
    用户的头像
    首次访问
    上次留言
    累计留言
    我的等级
    我的角色
    打赏二维码
    打赏博主
    Nuxt3 实战 (十一):添加路由 Transition 过渡效果和 Loading 动画
    点击复制本页信息
    微信扫一扫
    文章二维码
    文章图片 文章标题
    创建时间
  • 一 言
    确认删除此评论么? 确认
  • 本弹窗介绍内容来自,本网站不对其中内容负责。
    • 复制图片
    • 复制图片地址
    • 百度识图
    按住ctrl可打开默认菜单

    Nuxt3 实战 (十一):添加路由 Transition 过渡效果和 Loading 动画

    谢明伟 · 原创 ·
    前端开发Nuxt3 实战 · VueNuxt
    共 4789 字 · 约 1 分钟 · 758
    本文最后更新于2024年06月20日,已经过了140天没有更新,若内容或图片失效,请留言反馈

    页面过渡效果

    Nuxt3 利用 Vue组件 在页面和布局之间应用过渡效果。

    1. nuxt.config.ts 文件配置:

      js 代码:
      export default defineNuxtConfig({
        app: {
      pageTransition: { name: 'page', mode: 'out-in' }
        },
      })
    2. 在页面之间添加过渡效果,在 app.vue 文件中添加以下 CSS

      html 代码:
       <template>
      <NuxtPage />
       </template>
      
       <style>
       .page-enter-active,
       .page-leave-active {
      transition: all 0.4s;
       }
       .page-enter-from,
       .page-leave-to {
      opacity: 0;
      filter: blur(1rem);
       }
       </style>
    3. 要为页面设置不同的过渡效果,请在页面的 definePageMeta 中设置 pageTransition 键:

      html 代码:
      <script setup lang="ts">
      definePageMeta({
        pageTransition: {
      name: 'rotate'
        }
      })
      </script>

    如果你同时更改布局和页面,这里设置的页面过渡效果将不会运行。相反,你应该设置布局过渡效果

    布局过渡效果

    1. nuxt.config.ts 文件配置:

      js 代码:
      export default defineNuxtConfig({
        app: {
      layoutTransition: { name: 'layout', mode: 'out-in' }
        },
      })
    2. app.vue 文件中添加代码:

      html 代码:
      <template>
       <NuxtLayout>
      <NuxtPage />
       </NuxtLayout>
      </template>
      
      <style>
      .layout-enter-active,
      .layout-leave-active {
        transition: all 0.4s;
      }
      .layout-enter-from,
      .layout-leave-to {
        filter: grayscale(1);
      }
      </style>

    首屏加载动画

    Nuxt3 并没有直接提供 API,但我们利用 生命周期钩子 来完成我们期望的效果。

    1. 新建 components/FullLoading/index.vue 文件:

      html 代码:
        <template>
      <div
       class="fixed flex w-screen h-screen justify-center items-center flex-col z-[99] overflow-hidden bg-white dark:bg-slate-900"
      >
       <div
         class="relative w-12 h-12 rotate-[165deg] before:content-[''] after:content-[''] before:absolute after:absolute before:top-2/4 after:top-2/4 before:left-2/4 after:left-2/4 before:block after:block before:w-[.5em] after:w-[.5em] before:h-[.5em] after:h-[.5em] before:rounded after:rounded before:-translate-x-1/2 after:-translate-x-1/2 before:-translate-y-2/4 after:-translate-y-2/4 before:animate-[loaderBefore_2s_infinite] after:animate-[loaderAfter_2s_infinite]"
       />
      </div>
       </template>
       <style>
       @keyframes loaderBefore {
      0% {
       width: 0.5em;
       box-shadow:
         1em -0.5em rgba(225, 20, 98, 0.75),
         -1em 0.5em rgba(111, 202, 220, 0.75);
      }
      
      35% {
       width: 2.5em;
       box-shadow:
         0 -0.5em rgba(225, 20, 98, 0.75),
         0 0.5em rgba(111, 202, 220, 0.75);
      }
      
      70% {
       width: 0.5em;
       box-shadow:
         -1em -0.5em rgba(225, 20, 98, 0.75),
         1em 0.5em rgba(111, 202, 220, 0.75);
      }
      
      100% {
       box-shadow:
         1em -0.5em rgba(225, 20, 98, 0.75),
         -1em 0.5em rgba(111, 202, 220, 0.75);
      }
       }
      
       @keyframes loaderAfter {
      0% {
       height: 0.5em;
       box-shadow:
         0.5em 1em rgba(61, 184, 143, 0.75),
         -0.5em -1em rgba(233, 169, 32, 0.75);
      }
      
      35% {
       height: 2.5em;
       box-shadow:
         0.5em 0 rgba(61, 184, 143, 0.75),
         -0.5em 0 rgba(233, 169, 32, 0.75);
      }
      
      70% {
       height: 0.5em;
       box-shadow:
         0.5em -1em rgba(61, 184, 143, 0.75),
         -0.5em 1em rgba(233, 169, 32, 0.75);
      }
      
      100% {
       box-shadow:
         0.5em 1em rgba(61, 184, 143, 0.75),
         -0.5em -1em rgba(233, 169, 32, 0.75);
      }
       }
       </style>
    2. app.vue 添加代码:

      html 代码:
        <script setup lang="ts">
       const nuxtApp = useNuxtApp()
      
       // 是否首次加载
       const isFullLoading = ref(true)
      
       nuxtApp.hook('page:start', () => {
      isFullLoading.value = true
       })
      
       nuxtApp.hook('page:finish', () => {
      isFullLoading.value = false
       })
       </script>
      
       <template>
      <div>
       <!-- 首页加载全屏动画 -->
       <FullLoading v-if="isFullLoading" />
       <NuxtLayout>
         <NuxtPage />
       </NuxtLayout>
      </div>
       </template>

    页面进度条

    我们还可以添加一个页面进度条,Nuxt3 提供了 组件,我们直接在 app.vue 中添加:

    html 代码:
    <template>
      <NuxtLayout>
        <!-- 在页面导航之间显示一个进度条 -->
        <NuxtLoadingIndicator />
        <NuxtPage />
      </NuxtLayout>
    </template>

    效果预览

    总结

    通过本篇文章我们学习了如何在 Nuxt3 中添加路由切换过渡效果和首屏加载动画,没什么干货,按照官方文档操作就完事了。

    Github 仓库dream-site

    线上预览dream-site.cn

    声明:本文由 谢明伟(博主)原创,依据 CC-BY-NC-SA 4.0 许可协议 授权,转载请注明出处。

    还没有人喜爱这篇文章呢

    现在已有

    1

    条评论
    我要发表评论
    1. · · 海外
      • 等级:Lv.1
      • 角色:访客
      • 在线:很久之前
      头像
      沙发

      路由过渡动画有一个天坑存在。
      onMounted会被执行2次,而且这个问题存在已久...
      https://github.com/nuxt/nuxt/issues/27442

      评论
    博客logo 白雾茫茫丶 记录学习、生活和有趣的事 51统计 百度统计
    MOEICP 萌ICP备20236860号 ICP 粤ICP备2023007649号 ICP 粤公网安备44030402006402号

    💻️ 谢明伟 一天前 在线

    🕛

    本站已运行 2 年 311 天 19 小时 8 分

    🌳

    自豪地使用 Typecho 建站,并搭配 MyLife 主题
    白雾茫茫丶. © 2022 ~ 2024.
    网站logo

    白雾茫茫丶 记录学习、生活和有趣的事