vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue3路由跳转

Vue3中路由跳转优化技巧分享

作者:盛夏绽放

这篇文章主要为大家详细介绍了Vue3中路由跳转的相关优化技巧,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以跟随小编一起学习一下

为什么需要这个优化

想象一下你去快餐店点餐:

实现原理图解

手把手实现丝滑过渡效果

项目初始化准备

确保你有一个Vue3项目

npm init vue@latest my-project
cd my-project
npm install

安装必要依赖

npm install nprogress  # 如果要用进度条方案

创建全局加载组件(全屏方案)

src/components下新建GlobalLoading.vue

<template>
  <div v-if="isLoading" class="global-loading">
    <div class="loading-overlay"></div>
    <div class="loading-spinner">
      <div class="spinner"></div>
      <div class="loading-text">加载中...</div>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
const isLoading = ref(false);

const show = () => { isLoading.value = true };
const hide = () => { isLoading.value = false };

defineExpose({ show, hide });
</script>

<style scoped>
.global-loading {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 9999;
}
.loading-overlay {
  position: absolute;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(2px);
}
.loading-spinner {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
}
.spinner {
  border: 4px solid #f3f3f3;
  border-top: 4px solid #3498db;
  border-radius: 50%;
  width: 40px;
  height: 40px;
  animation: spin 1s linear infinite;
  margin: 0 auto 10px;
}
@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
.loading-text {
  color: white;
  font-size: 16px;
}
</style>

修改App.vue挂载组件

修改src/App.vue

<template>
  <RouterView />
  <GlobalLoading ref="globalLoading" />
</template>

<script setup>
import { ref, onMounted } from 'vue';
import GlobalLoading from '@/components/GlobalLoading.vue';

const globalLoading = ref(null);

// 全局挂载方法
onMounted(() => {
  window.__globalLoading = globalLoading.value;
});
</script>

配置路由守卫

修改src/router/index.js

import { createRouter, createWebHistory } from 'vue-router';
import HomeView from '../views/HomeView.vue';

const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/about',
    name: 'about',
    // 懒加载示例
    component: () => import('../views/AboutView.vue')
  }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

// 添加路由守卫
router.beforeEach(async (to, from, next) => {
  // 显示加载动画
  if (window.__globalLoading) {
    window.__globalLoading.show();
  }
  
  try {
    // 处理懒加载路由
    const matchedComponents = to.matched.flatMap(record => 
      Object.values(record.components)
    );
    
    await Promise.all(
      matchedComponents.map(component => {
        if (typeof component === 'function') {
          return component();
        }
        return Promise.resolve();
      })
    );
    
    next();
  } catch (err) {
    console.error('路由加载失败:', err);
    next(false);
  } finally {
    // 确保加载动画至少显示300ms
    setTimeout(() => {
      if (window.__globalLoading) {
        window.__globalLoading.hide();
      }
    }, 300);
  }
});

export default router;

进度条方案实现(可选)

src/router/index.js中添加

import NProgress from 'nprogress';
import 'nprogress/nprogress.css';

// 配置NProgress
NProgress.configure({ 
  showSpinner: false,
  minimum: 0.3,
  speed: 500
});

// 修改路由守卫
router.beforeEach((to, from, next) => {
  NProgress.start();
  next();
});

router.afterEach(() => {
  NProgress.done();
});

测试你的实现

创建测试视图

# 创建两个测试页面
touch src/views/HomeView.vue
touch src/views/AboutView.vue

AboutView.vue中添加延迟

<script setup>
// 模拟网络延迟
await new Promise(resolve => setTimeout(resolve, 1000));
</script>

添加导航链接

在任意页面添加:

<router-link to="/">Home</router-link> | 
<router-link to="/about">About</router-link>

效果验证

当你点击About链接时,应该能看到:

高级定制技巧

按路由类型显示不同加载效果

// 在路由配置中添加meta
{
  path: '/dashboard',
  component: () => import('@/views/Dashboard.vue'),
  meta: { loadingType: 'progress' } // 或'fullscreen'
}

// 修改路由守卫
router.beforeEach((to) => {
  if (to.meta.loadingType === 'progress') {
    NProgress.start();
  } else {
    window.__globalLoading?.show();
  }
});

添加骨架屏

<!-- 在懒加载组件中 -->
<template>
  <div v-if="!isLoaded">
    <!-- 骨架屏内容 -->
    <div class="skeleton-header"></div>
    <div class="skeleton-content"></div>
  </div>
  <div v-else>
    <!-- 实际内容 -->
  </div>
</template>

常见问题解决

加载动画不显示?

动画闪烁太快?

// 增加最小显示时间
let timer = setTimeout(() => {
  window.__globalLoading?.hide();
}, 500); // 至少显示500毫秒

// 在组件加载完成后清除计时器
await componentLoaded;
clearTimeout(timer);

TypeScript支持

// 在src/shims-global.d.ts中添加
declare global {
  interface Window {
    __globalLoading: {
      show: () => void;
      hide: () => void;
    };
  }
}

现在你的Vue3应用应该拥有了专业的路由过渡效果!可以通过调整动画样式、持续时间和触发条件来进一步优化用户体验。

常见问题解答

Q:为什么我的加载动画一闪而过?

A:就像你眨眼太快看不到东西一样,可能是因为:

Q:如何让不同路由显示不同加载动画?

A:可以这样定制:

router.beforeEach((to) => {
  if (to.meta.loadingType === 'fullscreen') {
    showFullLoading()
  } else {
    showProgressBar()
  }
})

Q:加载时用户还能操作页面吗?

A:默认不能,就像电梯运行时按钮会暂时失效。如果需要允许操作:

.loading-overlay {
  pointer-events: none; /* 添加这行 */
}

性能优化建议

预加载策略:像提前预热烤箱

// 在空闲时预加载可能访问的路由
import('@/views/About.vue')

骨架屏:像先把餐桌摆好再上菜

<!-- 在组件中添加骨架屏 -->
<template v-if="loading">
  <SkeletonLoader />
</template>

智能延迟:如果加载<300ms就不显示动画

let timer = setTimeout(showLoading, 300)
// 如果提前完成就取消计时器

到此这篇关于Vue3中路由跳转优化技巧分享的文章就介绍到这了,更多相关Vue3路由跳转内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文