Vue3 Composition API 实战指南:与 Vue Router 结合的路由逻辑处理

Vue3 的 Composition API 提供了一种更灵活、可复用的方式组织组件逻辑,而 Vue Router 是 Vue 生态中处理路由的核心工具。结合两者,可以高效管理路由逻辑,如导航守卫、参数获取和动态路由。本指南将逐步引导你从基础到实战,确保代码简洁、可维护。以下内容基于 Vue3 和 Vue Router 4 的官方文档和最佳实践。


1. 基础概念回顾

在开始实战前,确保理解核心概念:

  • Composition API:通过 setup() 函数组织逻辑,使用 refreactive 等响应式 API。
  • Vue Router:用于定义路由规则、处理导航和守卫。
  • 关键钩子useRouter 访问路由实例,useRoute 获取当前路由信息。

例如,在组件中导入钩子:

import { useRouter, useRoute } from 'vue-router';
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const router = useRouter(); // 用于导航操作
    const route = useRoute();   // 用于获取当前路由状态
    const userId = ref(null);   // 响应式变量存储参数

    onMounted(() => {
      userId.value = route.params.id; // 获取路由参数
    });

    return { userId };
  }
};


2. 路由逻辑处理:核心场景

以下是常见路由逻辑的实战处理方式,使用 Composition API 实现。

2.1 获取路由参数

在动态路由中,经常需要从 URL 提取参数(如用户 ID)。使用 useRoute 简化过程:

  • 步骤
    1. 定义路由规则(在 router/index.js 中):{ path: '/user/:id', component: User }
    2. 在组件中通过 route.params 访问参数。
  • 代码示例
import { useRoute } from 'vue-router';
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const route = useRoute();
    const userData = ref(null);

    onMounted(async () => {
      const id = route.params.id; // 获取参数,如 /user/123 中的 123
      // 模拟 API 调用
      userData.value = await fetchUser(id);
    });

    return { userData };
  }
};

2.2 编程式导航

使用 useRouter 实现按钮点击跳转或其他逻辑导航:

  • 场景:登录后跳转到首页。
  • 代码示例
import { useRouter } from 'vue-router';
import { ref } from 'vue';

export default {
  setup() {
    const router = useRouter();
    const isLoggedIn = ref(false);

    function handleLogin() {
      isLoggedIn.value = true;
      router.push('/dashboard'); // 导航到仪表盘
    }

    return { isLoggedIn, handleLogin };
  }
};

2.3 导航守卫

在 Composition API 中实现全局或路由级守卫,控制访问权限:

  • 全局守卫(在 router/index.js 中定义):
    import { createRouter } from 'vue-router';
    
    const router = createRouter({ /* 路由配置 */ });
    
    router.beforeEach((to, from, next) => {
      if (to.meta.requiresAuth && !isAuthenticated()) {
        next('/login'); // 重定向到登录页
      } else {
        next();
      }
    });
    

  • 组件内守卫:使用 onBeforeRouteUpdateonBeforeRouteLeave 钩子。
    import { onBeforeRouteLeave } from 'vue-router';
    import { ref } from 'vue';
    
    export default {
      setup() {
        const hasUnsavedChanges = ref(true);
    
        onBeforeRouteLeave((to, from, next) => {
          if (hasUnsavedChanges.value) {
            const confirmLeave = window.confirm('有未保存的更改,确定离开?');
            if (confirmLeave) next();
            else next(false); // 取消导航
          } else {
            next();
          }
        });
    
        return { hasUnsavedChanges };
      }
    };
    


3. 实战示例:登录验证与路由保护

构建一个完整场景:用户登录后访问受保护的路由,否则重定向到登录页。

  • 步骤

    1. 定义路由:创建 /login/dashboard 等路由。
    2. 使用 Pinia 或 Vuex 管理登录状态(推荐 Pinia 以匹配 Composition API 风格)。
    3. 在全局守卫中检查状态。
  • 代码实现

    • 路由配置(router/index.js):
      import { createRouter, createWebHistory } from 'vue-router';
      
      const routes = [
        { path: '/', redirect: '/login' },
        { path: '/login', component: () => import('@/views/Login.vue') },
        { 
          path: '/dashboard', 
          component: () => import('@/views/Dashboard.vue'),
          meta: { requiresAuth: true } // 标记需要认证
        }
      ];
      
      const router = createRouter({
        history: createWebHistory(),
        routes
      });
      
      router.beforeEach((to, from, next) => {
        const isAuthenticated = localStorage.getItem('token'); // 简单示例,实际用 Pinia
        if (to.meta.requiresAuth && !isAuthenticated) {
          next('/login');
        } else {
          next();
        }
      });
      
      export default router;
      

    • 登录组件(Login.vue):
      import { useRouter } from 'vue-router';
      import { ref } from 'vue';
      
      export default {
        setup() {
          const router = useRouter();
          const username = ref('');
          const password = ref('');
      
          function submitLogin() {
            // 模拟登录成功
            localStorage.setItem('token', 'user-token');
            router.push('/dashboard');
          }
      
          return { username, password, submitLogin };
        }
      };
      


4. 最佳实践与常见问题
  • 最佳实践
    • 使用 TypeScript:增强类型安全,例如定义 route.params 的类型。
    • 逻辑复用:将路由逻辑提取到 composable 函数中,如创建 useNavigation 钩子。
      // composables/useNavigation.js
      import { useRouter } from 'vue-router';
      
      export function useNavigation() {
        const router = useRouter();
        
        function navigateTo(path) {
          router.push(path);
        }
      
        return { navigateTo };
      }
      

    • 错误处理:在导航中添加 catch 块处理错误:router.push('/home').catch(err => console.error(err))
  • 常见问题
    • 问题:路由参数变化时组件不更新?
      解决:使用 watch 监听 route.params
      import { watch } from 'vue';
      import { useRoute } from 'vue-router';
      
      setup() {
        const route = useRoute();
        watch(() => route.params.id, (newId) => {
          // 处理参数变化
        });
      }
      

    • 问题:守卫中异步逻辑混乱?
      解决:用 async/await 确保顺序执行。

5. 总结

通过 Composition API 结合 Vue Router,你能更优雅地处理路由逻辑:

  • 优势:逻辑集中、易于测试和复用。
  • 核心技巧:善用 useRouteruseRoute 和导航守卫。
  • 适用场景:SPA 应用、权限控制、动态路由等。

继续探索时,参考 Vue Router 官方文档Vue3 指南,结合实际项目迭代优化。如果有具体问题(如嵌套路由或懒加载),可进一步讨论!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐