vue进阶-vue-route

Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。

本章只做学习记录,详尽的内容一定要去官网查看 📚api文档: Vue Router-Vue.js 的官方路由

1. 路由的基本使用

1.1 安装vue-router

npm install vue-router@4

1.2 使用vue-router

📍1、src下创建一个叫 router 的文件夹,并创建 index.js,创建并暴露一个路由器 router

在这里插入图片描述

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '@/components/Home.vue'
import About from '@/components/About.vue'

// 1. 定义一些路由
// 每个路由都需要映射到一个组件。
const routes = [
    { path: '/', component: Home },
    { path: '/about', component: About },
]

// 2. 创建路由实例并传递 `routes` 配置
const router = createRouter({
    // 2. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
    history: createWebHashHistory(),
    routes, // `routes: routes` 的缩写
})

export default router

📍2、创建需要的组件

在这里插入图片描述

📍3、在 main.js 中导入并 use router

在这里插入图片描述

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

//创建实例,使用 router,并挂载根实例
createApp(App).use(router).mount('#app')

📍4、App.vue 中使用路由

<template>
  <h1>Hello Vue-Route!</h1>
  <p>
    <!--使用 router-link 组件进行导航 -->
    <!--通过传递 `to` 来指定链接 -->
    <!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
    <router-link to="/">Go to Home</router-link>  |  
    <router-link to="/about">Go to About</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</template>

<script>
export default {
  name: 'App',
  components: {}
}
</script>

<style>
...
}
</style>

router-view 将显示与 url 对应的组件。你可以把它放在任何地方,以适应你的布局。

📍5、测试
点击 “Go to Home”,显示“this is home”
在这里插入图片描述

点击 “Go to About”,显示“this is about”
在这里插入图片描述

2. 动态路由匹配

很多时候,我们需要将给定匹配模式的路由映射到同一个组件。例如:/user/12/user/13 映射到同一个组件。在 Vue Router 中,我们可以在路径中使用一个动态字段来实现,我们称之为 路径参数

📍1、App.vue 使用路由

<template>
  <h1>Hello Vue-Route!</h1>
  <p>
    <!--使用 router-link 组件进行导航 -->
    <!--通过传递 `to` 来指定链接 -->
    <!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
    <router-link to="/">Go to Home</router-link>  |  
    <router-link to="/about">Go to About</router-link> | 
    <router-link to="/user/12"> 12号用户 </router-link> | 
    <router-link to="/user/13"> 13号用户 </router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</template>

...

📍2、router/index.js 新增动态路由映射

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '@/components/Home.vue'
import About from '@/components/About.vue'
import User from '@/components/User.vue'

// 1. 定义一些路由
// 每个路由都需要映射到一个组件。
const routes = [
    { path: '/', component: Home },
    { path: '/about', component: About },
    { path: '/user/:id', component: User }
]

...

路径参数用冒号:表示。当一个路由被匹配时,它的 params 的值将在每个组件中this.$route.params 的形式暴露出来。因此,我们可以通过更新 User 的模板来呈现当前的用户 ID:

📍3、User 组件

<template>
    My id is {{ $route.params.id }}
</template>

📍4、测试

点击 “12号用户”,显示“My id is 12”
在这里插入图片描述

点击 “13号用户”,显示“My id is 13”
在这里插入图片描述

⚠️注: 你可以在同一个路由中设置有多个路径参数,它们会映射到 $route.params 上的相应字段。例如:

匹配模式匹配路径$route.params
/users/:username/users/eduardo{ username: ‘eduardo’ }
/users/:username/posts/:postId/users/eduardo/posts/123{ username: ‘eduardo’, postId: ‘123’ }

除了 $route.params 之外,$route 对象还公开了其他有用的信息,如 $route.query(如果 URL 中存在参数)、$route.hash 等。

3. 路由的匹配语法

3.1 参数中自定义正则

当定义像 :userId 这样的参数时,我们内部可以使用正则表达进行修饰。

const routes = [
  // /:orderId -> 仅匹配数字
  { path: '/:orderId(\\d+)', component: component1},
  // /:productName -> 匹配其他任何内容
  { path: '/:productName', component: component2},
]

现在,转到 /25 将匹配 /:orderId,其他情况将会匹配 /:productName。routes 数组的顺序并不重要!

3.2 参数数组

如果你需要匹配具有多个部分的路由,如 /first/second/third,你应该用 *(0 个或多个)和 +(1 个或多个)将参数标记为可重复:

const routes = [
  // /:chapters ->  匹配 /one, /one/two, /one/two/three, 等
  { path: '/:chapters+' },
  // /:chapters -> 匹配 /, /one, /one/two, /one/two/three, 等
  { path: '/:chapters*' },
]

这将为你提供一个参数数组而不是一个字符串,并且在使用命名路由时也需要你传递一个数组:

📍1、router/index.js 新增动态路由映射:

const routes = [
    ...
    { path: '/user/:id*', component: User }
]

📍2、App.vue 使用路由

<router-link to="/user/11/22/33"> 参数数组 </router-link>

📍3、测试

点击 “参数数组”,显示“My id is [ “11”, “22”, “33” ]”

在这里插入图片描述

4. 嵌套路由

一些应用程序的 UI 由多层嵌套的组件组成。例如:/user/johnny/profile/user/johnny/posts中,profile、posts 属于 johnny 下属 url,可以配置嵌套路由来表达这种关系。

我们上述案例中的 <router-view> 是一个顶层router-view。它渲染顶层路由匹配的组件。同样地,一个被渲染的组件也可以包含自己嵌套的 <router-view>。例如,如果我们在 User 组件的模板内添加一个 <router-view>

📍1、User 组件添加<router-view>

<template>
    My id is {{ $route.params.id }}
    <p>
    <router-link to="/user/12/profile">头像</router-link>  |  
    <router-link to="/user/12/posts">岗位</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</template>

📍2、router/index.js 新增子路由映射

要将组件渲染到这个嵌套的 router-view 中,我们需要在路由中配置 children

...
import User from '@/components/user'
import UserProfile from '@/components/user/UserProfile.vue'
import UserPosts from '@/components/user/UserPosts.vue'

// 1. 定义一些路由
// 每个路由都需要映射到一个组件。
const routes = [
    { path: '/', component: Home },
    { path: '/about', component: About },
    { 
        path: '/user/:id', 
        component: User,
        children: [
            {
              // 当 /user/:id/profile 匹配成功
              // UserProfile 将被渲染到 User 的 <router-view> 内部
              path: 'profile',
              component: UserProfile,
            },
            {
              // 当 /user/:id/posts 匹配成功
              // UserPosts 将被渲染到 User 的 <router-view> 内部
              path: 'posts',
              component: UserPosts,
            },
        ]
    }
]

...

children 配置只是另一个路由数组,就像 routes 本身一样。因此,你可以根据自己的需要,不断地嵌套视图

📍3、子组件
在这里插入图片描述

📍4、测试

点击 “头像”

在这里插入图片描述
点击 “岗位”
在这里插入图片描述

⚠️注意1:⚡如果直接访问子路由,对应的父路由组件也会随之一起加载。

比如,直接访问 http://localhost:8080/user/12/profile,父组件也会随之加载。

在这里插入图片描述

⚠️注意2:⚡子路由 path 可以是相对路径,比如上例中的 path: 'profile';也可以是绝对路径:path: '/user/:id/profile',推荐 相对路径

嵌套路由传参

上述案例有个问题,User 组件的访问路径是写死的 <router-link to="/user/12/profile">头像</router-link>,我们可以通过 v-bind动态获取上层的路径参数。

<template>
    My id is {{ $route.params.id }}
    <p>
    <router-link :to=" '/user/' + $route.params.id + '/profile' ">头像</router-link>  |  
    <router-link :to=" '/user/' + $route.params.id + '/posts' ">岗位</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</template>

5. 路由命名

除了 path 之外,你还可以为任何路由提供 name

📍router/index.js :

const routes = [
    {
        path: '/', name: 'home', component: Home
    },
    {
        path: '/about', name: 'about', component: About
    },
    {
        path: '/user/:id',
        name: 'user',
        component: User,
        children: [
            {
                // 当 /user/:id/profile 匹配成功
                // UserProfile 将被渲染到 User 的 <router-view> 内部
                path: 'profile',
                component: UserProfile,
            },
            {
                // 当 /user/:id/posts 匹配成功
                // UserPosts 将被渲染到 User 的 <router-view> 内部
                path: 'posts',
                component: UserPosts,
            },
        ]
    }
]

为路由路径命名。

📍App.vue:

<template>
  <h1>Hello Vue-Route!</h1>
  <p>
    <!--使用 router-link 组件进行导航 -->
    <!--通过传递 `to` 来指定链接 -->
    <!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
    <!-- <router-link to="/">Go to Home</router-link>  |   -->
    <router-link :to="{name: 'home'}">Go to Home</router-link>  |  
    <router-link :to="{name: 'about'}">Go to About</router-link> | 
    <router-link :to="{name: 'user', params: {id: 12}}"> 12号用户 </router-link> | 
    <router-link :to="{name: 'user', params: {id: 13}}"> 13号用户 </router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</template>

要链接到一个命名的路由,可以向 router-link 组件的 to 属性传递一个对象,路径参数 通过 params 传递。

⚠️注意:⚡此处的 to 属性需要通过 v-bind 修饰。

6. 视图命名

有时候想同时 (同级) 展示多个视图,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。如果 router-view 没有设置名字,那么默认为 default

📍App.vue:

<template>
  ...
  
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view name="LeftSidebar"></router-view> |
  <router-view></router-view> | 
  <router-view name="RightSidebar"></router-view>
</template>

📍router/index.js :

一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components 配置 (带上 s):

const routes = [
    {
        path: '/', name: 'home', component: Home
    },
    {
        path: '/about', 
        name: 'about', 
        //component: About
        components: {
            LeftSidebar: UserProfile,
            default: About,
            RightSidebar: UserPosts
        }
    },
    {
        path: '/user/:id',
        name: 'user',
        component: User,
        children: [
            {
                // 当 /user/:id/profile 匹配成功
                // UserProfile 将被渲染到 User 的 <router-view> 内部
                path: 'profile',
                component: UserProfile,
            },
            {
                // 当 /user/:id/posts 匹配成功
                // UserPosts 将被渲染到 User 的 <router-view> 内部
                path: 'posts',
                component: UserPosts,
            },
        ]
    }
]

设置 url=/about 的视图 LeftSidebar 的加载组件为 UserProfile,视图 default 的加载组件为 About,视图 RightSidebar 的加载组件为 UserPosts

📍测试:

点击 “Go to Home”
在这里插入图片描述

点击 “Go to About”
在这里插入图片描述

7. 编程式导航

除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。

在 Vue 实例中,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push。当你点击 <router-link> 时,内部会调用这个方法,所以点击 <router-link :to="..."> 相当于调用 router.push(...)

声明式编程式
<router-link :to=“…”>router.push(…)

该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:

// 字符串路径
router.push('/users/eduardo')

// 带有路径的对象
router.push({ path: '/users/eduardo' })

// 命名的路由,并加上参数,让路由建立 url
router.push({ name: 'user', params: { username: 'eduardo' } })

// 带查询参数,结果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })

// 带 hash,结果是 /about#team
router.push({ path: '/about', hash: '#team' })
注意:如果提供了 path,params 会被忽略。

router.push 和所有其他导航方法都会返回一个 Promise,让我们可以等到导航完成后才知道是成功还是失败。

📍App.vue:

<template>
  <h1>Hello Vue-Route!</h1>
  <p>
    <!--使用 router-link 组件进行导航 -->
    <!--通过传递 `to` 来指定链接 -->
    <!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
    <!-- <router-link to="/">Go to Home</router-link>  |   -->
    <router-link :to="{name: 'home'}">Go to Home</router-link>  |  
    <router-link :to="{name: 'about'}">Go to About</router-link> | 
    <router-link :to="{name: 'user', params: {id: 12}}"> 12号用户 </router-link> | 
    <router-link :to="{name: 'user', params: {id: 13}}"> 13号用户 </router-link>
    <button @click="tiaozhuan">push跳转</button>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view> 
</template>

<script>

export default {
  name: 'App',
  components: {},
  methods: {
    tiaozhuan(){
      this.$router.push({
        name: 'user',
        params: {
          id: 12
        }
      })
    }
  }
}
</script>

...

点击 “push跳转”,地址栏跳转到 http://localhost:8080/#/user/12

在这里插入图片描述

替换当前位置

它的作用类似于 router.push,唯一不同的是,它在导航时不会向 history 添加新记录,正如它的名字所暗示的那样——它取代了当前的条目。

声明式编程式
<router-link :to=“…” replace>router.replace(…)

8. 重定向和别名

通过 redirect 配置重定向

const routes = [{ path: '/home', component: Component, redirect: '/' }]

//重定向的目标也可以是一个命名的路由
const routes = [{ path: '/home', component: Component, redirect: { name: 'homepage' } }]

通过 alias 配置别名

const routes = [{ path: '/', component: Homepage, alias: '/home' }]

9. 路由组件传参

在第二节提到动态路由匹配,通过 {{ $route.params.id }} 获取路径参数,这样会使得组件和路由紧密耦合,这限制了组件的灵活性。为了组件的灵活性,我们可以通过 props 配置来解耦

//路由 props: true route.params 将被传递给组件的 props
const routes = [{ path: '/user/:id', component: User, props: true }]

//组件 通过 props 指定传递的路径参数
const User = {
  // 请确保添加一个与路由参数完全相同的 prop 名
  props: ['id'],
  template: '<div>User {{ id }}</div>'
}

📍1、router/index.js 路由器配置props:true

在这里插入图片描述

📍2、路由映射的组件通过 props 指定参数

在这里插入图片描述
在这里插入图片描述

📍3、测试
在这里插入图片描述

9.1、params传参

params 传参又可分为 声明式编程式 两种方式:

  • 声明式 router-link:该方式是通过router-link组件的to属性实现,子路由需要提前配置好参数
 <router-link :to="/child/1"> 跳转到子路由 </router-link>
 
{
    path: '/child/:id',
    component: Child
}
  • 编程式 this.$router.push:同样需要子路由提前配置好参数。
{
    path: '/child/:id',
    component: Child
}
  
this.$router.push({
   path:'/child/${id}',
})

接收: this.$route.params.id

布尔模式

props 设置为 true 时,route.params 将被设置为组件的 props

命名视图

对于有命名视图的路由,你必须为每个命名视图定义 props 配置:

const routes = [
  {
    path: '/user/:id',
    components: { default: User, LeftSidebar: UserProfile },
    props: { default: true, sidebar: false }
  }
]

对象模式

props静态的时候很有用。

const routes = [
    {
        path: '/user/:id',
        name: 'user',
        component: User,
        props: { id: 20 },
        ...
    }
]

在这里插入图片描述

函数模式

你可以创建一个返回 props 的函数。

const routes = [
  {
    path: '/search',
    component: SearchUser,
    props: route => ({ query: route.query.q })
  }
]

URL /search?q=vue 将传递 {query: 'vue'} 作为 props 传给 SearchUser 组件。

9.2、query 传参

当需要传递的参数过多,不想放在 URL 时,可以通过参数传参。

下面演示参数、query传参:

📍1、router/index.js 路由器配置 函数模式props

const routes = [
    ...
    {
        path: '/query/:id', 
        name: 'ComponentA', 
        component: ComponentA,
        props: route => ({ 
            id: route.params.id,
            title: route.query.title,
            userName: route.query.userName
        })
    }
]

路由组件 定义访问路径路由名称映射组件函数模式返回传递给映射组件的参数集

📍2、主组件 App.vue 声明式导航

<template>
  <h1>Hello Vue-Route!</h1>
  <p>
    ...
    <router-link :to="{name: 'ComponentA', params: { id: '1001' }, query: {title: '路由组件query传参', userName: 'Jack'}}"> query传参 </router-link>
  </p>
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</template>

主组件 定义声明式导航,传入 name、params、query。

📍3、新建组件 ComponentA

<template>
    this is ComponentA for {{ id }}
    <br />
    title = {{title}}, userName = {{userName}}
</template>
<script>
export default {
    props: ['id', 'title', 'userName']
}
</script>

组件 内通过 props 获取传入的参数。

📍4、测试

在这里插入图片描述

点击“query传参”,请求 url 为 http://localhost:8080/query/1001?title=路由组件query传参&userName=Jack,组件内参数 ‘id’, ‘title’, ‘userName’ 均获取成功。

10. 不同的历史模式

Hash 模式

hash 模式是用 createWebHashHistory() 创建的,它在内部传递的实际 URL 之前使用了一个哈希字符(#

HTML5 模式

createWebHistory() 创建 HTML5 模式,推荐使用这个模式。需要服务器配置。

11. 导航守卫

相当于拦截器vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的单个路由独享的,或者组件级的。

全局前置守卫

你可以使用 router.beforeEach 注册一个全局前置守卫

const router = createRouter({ ... })

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

路由独享的守卫

const routes = [
  {
    path: '/users/:id',
    component: UserDetails,
    beforeEnter: (to, from) => {
      // reject the navigation
      return false
    },
  },
]

组件内的守卫

const UserDetails = {
  template: `...`,
  beforeRouteEnter(to, from) {
    // 在渲染该组件的对应路由被验证前调用
    // 不能获取组件实例 `this` !
    // 因为当守卫执行时,组件实例还没被创建!
  },
  beforeRouteUpdate(to, from) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
    // 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
  },
  beforeRouteLeave(to, from) {
    // 在导航离开渲染该组件的对应路由时调用
    // 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
  },
}
  • beforeRouteEnter
  • beforeRouteUpdate
  • beforeRouteLeave

12. 路由元信息

有時候需要添加附加信息到路由上,如过渡名称、谁可以访问路由等。这些事情可以通过接收属性对象的 meta 属性来实现,并且它可以在路由地址和导航守卫上都被访问到。

📍1、route/index.js

import { createRouter, createWebHashHistory } from 'vue-router'
import About from '@/components/About.vue'
import Home from '@/components/Home.vue'

const routes = [
    {
        path: '/', 
        name: 'home', 
        component: Home,  
        // 指定路由的 meta 属性
        meta: { requiresAuth: false, title: 'home-title' }
    },
    {
        path: '/about', 
        name: 'about', 
        component: About,
        // 指定路由的 meta 属性
        meta: { requiresAuth: false, title: 'about-title' }
    }
]

// 2. 创建路由实例并传递 `routes` 配置
const router = createRouter({
    // 2. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
    history: createWebHashHistory(),
    routes // `routes: routes` 的缩写
})

// 3.新增全局前置守卫,打印目标路由对象
router.beforeEach((to, from, next) => {
    console.log(to)
    next();
    // 而不是去检查每条路由记录
    // to.matched.some(record => record.meta.requiresAuth)
   
  })
  

export default router

映射组件内声明 meta 属性内容,通过全局守卫获取 meta 值。

访问 “/about”、“/” 分别打印:
在这里插入图片描述

13. 动态路由

前面章节路由设置都是硬代码写死,而实际项目中,路由的配置都是动态的,比如,路由设置在数据库,需要请求后台返回的数据动态设置路由。

动态路由主要通过两个函数实现。router.addRoute()router.removeRoute()。它们只注册一个新的路由,也就是说,如果新增加的路由与当前位置相匹配,就需要你用 router.push()router.replace() 来手动导航,才能显示该新路由。

在这里插入图片描述

详尽的案例一定要去官网查看api文档: Vue Router-Vue.js 的官方路由

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会叫的狼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值