Vue3学习(五)-----路由

262 阅读5分钟

路由 Vue-router

安装:

npm i vue-router@4

1. 创建两个子组件Home.vue Mine.vue

<template>
<div style="background-color: red;">
<p>子组件-----Home</p>
</div>
</template>
<script setup lang="ts">
</script>



<template>
<div style="background-color: bisque;">
<p>子组件-----Mine</p>
</div>
</template>
<script setup lang="ts">
</script>

2. 创建路由配置

router/index.ts 文件中,定义你的路由配置: 常用配置参数:

“path” 用于配置访问路径
“name” 用于给该路由命名
“component” 表示需要映射的组件
“redirect”表示重定向
“children”用于路由嵌套
函数: createRouter: 用于创建路由实例,接收一个配置对象作为参数。

参数: history:用于定义路由模式,常用的有 createWebHistory()createWebHashHistory()
routes:定义路由规则的数组。

createWebHistory: 创建 HTML5 模式的历史记录。

参数: base:可选,应用的基路径。

createWebHashHistory: 创建哈希模式的历史记录(URL 带有 #)。

参数: base:可选,应用的基路径。

import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
import Home from "../components/Home.vue";
import Mine from "../components/Mine.vue";
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/Mine',
name: 'Mine',
component: Mine
}
];
const router = createRouter({
history: createWebHistory(),
routes,
});

export default router;

3. 在 Vue 实例中使用路由

main.ts 文件中,导入并使用路由:

import router from './router'
const app = createApp(App);

app.use(router)

APP.vue中使用路由功能:使用 <router-link> 进行导航,使用 <router-view> 显示匹配的组件

<template>
<router-link to="/">主页</router-link>
<router-link to="/Mine">我的页面</router-link>
<router-view></router-view>
</template>

4. 嵌套路由

实际项目中的应用界面通常由多层嵌套的组件组合而成。在配置嵌套路由时,在父路由中,增加children参数,添加对应的子路由 语法为:

routes: [{
    path: '父路由路径',
    component: 父组件,
    children: [
      { path: '子路由路径1', component: 子组件1 },
      { path: '子路由路径2', component: 子组件2 }
    ]
}]

创建一个Home_child.vue

<template>
<div>
<p>Home中Child组件</p>
</div>
</template>
<script setup lang="ts">
</script>

配置中增加子路由:

{
path: '/',
name: 'Home',
component: Home,
children: [
{ path: 'child',
name: 'Home_child',
component: Home_child
}
]
},

Home.vue 使用路由

<template>

<div style="background-color: red;">

<p>子组件-----Home</p>

<router-link to="child">child</router-link>

<router-view></router-view>

</div>

</template>

<script setup lang="ts">

</script>

5. 动态路由

创建一个User.vue,并配置好动态路由,在User.vue中展示对应的数据
路径参数 用冒号 : 表示。当一个路由被匹配时,它的 params 的值将在每个组件中以 route.params 的形式暴露出来。

Xnip2024-10-24_09-33-51.png

6. 路由传参

方式一:路由属性配置传参,需进行组件的路由规则配置 直接在路由配置上加上:params进行传参

{

path: '/User/:username/id/:id',

name: 'UserParams',

component: User

},

<router-link to="/User/li/id/11">用户11</router-link>
//获取值
<p>{{ $route.params.username }}</p>

<p>{{ $route.params.id }}</p>

方式二:query方式传参,可以由name和path引入,无需配置组件的路由规则

{

path: '/User',

name: 'User',

component: User

}

router.push({path:"/User", query: {id: '123',username:'hello'}});

//获取值
<p>{{ $route.query.username }}</p>

<p>{{ $route.query.id }}</p>

方式三:params方式传参,只能由name引入,需进行组件的路由规则配置

{

path: '/User/:username/id/:id',

name: 'UserParams',

component: User

},

router.push({name:"UserParams", params: {username: '张三', id: '555'}});
//获取值
<p>{{ $route.params.username }}</p>

<p>{{ $route.params.id }}</p>

Xnip2024-10-24_10-48-57.png

6. 动态添加路由

import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
const routes: Array<RouteRecordRaw> = []

const router = createRouter({

history: createWebHistory(),

routes,

});

//动态添加路由

const homeRoute = {

path: '/',

name: 'Home',

component: ()=>import('../components/Home.vue'),

}

const mineRoute = {

path: '/Mine',

name: 'Mine',

component: ()=>import('../components/Mine.vue'),

}

const userRoute = {

path: '/User',

name: 'User',

component: ()=>import('../components/User.vue'),

}

const userComRoute = {

path: '/User/:username/id/:id',

name: 'UserParams',

component: ()=>import('../components/User.vue'),

}

//router.addRoute()动态添加,实际开发中根据if判断

  


router.addRoute(homeRoute);

router.addRoute(mineRoute);

router.addRoute(userRoute);

router.addRoute(userComRoute);

//添加子路由

router.addRoute('Home',{

path: 'child',

name: 'Home_child',

component: ()=>import("../components/Home_child.vue")

})

export default router;

7. 删除路由

删除路由有三种方式:

  1. 添加一个与之前路由一样名字的路由,之前的路由会被替代删除
  2. 调用删除函数router.removeRoute('路由name')
  3. 通过addRoute()返回值回调

Xnip2024-10-24_13-21-06.png

8. 导航守卫

vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航

8.1 全局前置守卫
const router = createRouter({ ... })

router.beforeEach((to, from) => {
  // ...
  // 返回 false 以取消导航
  return false
})
  • to: 即将要进入的目标 
  • from: 当前导航正要离开的路由

返回值:

  • false: 取消当前的导航。
  • 一个路由地址: 通过一个路由地址重定向到一个不同的地址,如同调用 router.push(),且可以传入诸如 replace: true 或 name: 'home' 之类的选项。它会中断当前的导航,同时用相同的 from 创建一个新导航。
 router.beforeEach(async (to, from) => {
   if (
     // 检查用户是否已登录
     !isAuthenticated &&
     // ❗️ 避免无限重定向
     to.name !== 'Login'
   ) {
     // 将用户重定向到登录页面
     return { name: 'Login' }
   }
 })
  • 可选的第三个参数 next :
router.beforeEach((to, from, next) => {
  if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
  else next()
})
8.2 全局解析守卫

你可以用 router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,因为它在每次导航时都会触发,不同的是,解析守卫刚好会在导航被确认之前、所有组件内守卫和异步路由组件被解析之后调用。
示例:根据路由在元信息中的 requiresCamera 属性确保用户访问摄像头的权限:

router.beforeResolve(async to => {
  if (to.meta.requiresCamera) {
    try {
      await askForCameraPermission()
    } catch (error) {
      if (error instanceof NotAllowedError) {
        // ... 处理错误,然后取消导航
        return false
      } else {
        // 意料之外的错误,取消导航并把错误传给全局处理器
        throw error
      }
    }
  }
})
8.3 全局后置钩子

允许你在每次成功完成导航后执行一些额外的逻辑。

router.afterEach((to, from, failure) => {
    
})
  • to: 这是你即将到达的目标路由对象

  • from: 这是你离开的来源路由对象

  • failure: 这是导航失败的原因(如果有的话)

router.afterEach((to, from, failure)=>{

if(!failure) sendToAnalytics(to.fullPath)

})

function sendToAnalytics(path){

console.log(path)

}

可以做的一些事情:

  • 记录数据:细心地跟踪用户的导航数据,帮助你了解他们的浏览轨迹。
  • 更新页面标题:虽然更新标题更常见于 beforeEach 钩子,但有时在后置钩子中更新也能确保标题与内容的完美契合。
  • 进行分析:执行各种后续分析任务,从用户行为到页面性能,一应俱全。
  • 清理工作:完成导航后的清理工作,例如重置应用状态,让一切恢复整洁。
8.4 路由独享守卫

一个路由中配置的单独守卫

router.addRoute('Home',{

path: 'child',

name: 'Home_child',

beforeEnter: (to, from) => {

return false

},

component: ()=>import("../components/Home_child.vue")

})

beforeEnter 守卫 只在进入路由时触发,不会在 paramsqueryhash 改变时触发

8.5 组件内守卫

在路由组件内直接定义路由导航守卫

<script setup lang="ts">

import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router';

  


onBeforeRouteUpdate(async (to, from) => {

//守卫在当前路由发生改变时触发,例如 : 从 /c/100 跳转到 /c/200

})

onBeforeRouteLeave((to, from) => {

//守卫在当前路由离开时触发,例如 :从 /c 跳转到 /a

})

</script>