Vue-router 使用教程


共计 6414 个字符,预计需要花费 17 分钟才能阅读完成。

1. 简介

vue-router 是官方提供的路由插件。Vue 中的路由其实就是路径和组件之间的对应关系,因为 vue 是单页应用类网站,所以创建的网站都在一个页面中。当需要展示不同的内容时,就需要通过修改浏览器的访问路径,来达到根据路径展示不同组件的目的。

官方文档:https://router.vuejs.org/zh/

可以使用 <router-link> 组件进行导航,使用 <router-view> 做为路由出口,即点击导航所对应的组件。

2. 简单使用

vue2 中使用 vue-router 分为以下几个步骤:

  • 安装 vue-router
  • 引入 vue-router
  • 注册 vue-router 插件
  • 创建 VueRouter 实例
  • VueRouter 注入 Vue 实例

其中第一步当然是在控制台完成。

npm install vue-router

接下来要创建 VueRouter,一般会在 src目录下新建一个 router/index.js 文件。

// 引入 vue-router
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/components/Home.vue';
import About from '@/components/About.vue';

// 注册 vue-router 插件。
// 告诉 Vue.js 使用 VueRouter 插件,所有插件使用之前都需要进行注册
Vue.use(VueRouter)

// 创建 VueRouter 实例
export default new VueRouter({
    routes: [{
        path: '/',
        name: 'home',
        component: Home
    }, {
        path: '/about',
        name: 'about',
        component: About
    }]
});

main.js 中引入 VueRouter,并注入。

import router from './router'

new Vue({
    el: '#app',
    components: { App },
    template: '<App/>',
    router
})

在组件中这样使用即可。

<template>
  <div id="app">
    <h1>Hello App!</h1>
    <div class="nav">
      <router-link to="/">Home</router-link>
      <router-link to="/about">About</router-link>
    </div>
    <div class="content">
      <router-view></router-view>
    </div>
  </div>
</template>

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

<style scoped>
  .content {
    background-color: skyblue;
  }
</style>

3. 嵌套路由

一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的片段通常对应于特定的嵌套组件结构。

其中 routes 定义如下:

const router = new VueRouter({
    routes: [{
        path: '/home',
        name: 'home',
        component: Home,
        children: [
            { path: 'foo', component: Foo },
            { path: 'bar', component: Bar }
        ]
    }, {
        path: '/about',
        name: 'about',
        component: About
    }]
});

可以看见 FooBar 组件都在 /home 路由下,他们的完整路由为 /home/foo/home/bar。所以,此时 Home 应该包含 FooBar 组件。

Home.vue 内容如下:

<template>
    <div>
        <h2>我是Home组件</h2>
        <router-link to="/home/foo">Foo</router-link>
        <router-link to="/home/bar">Bar</router-link>
        <router-view></router-view>
    </div>
</template>

<script>
    export default {
        name: 'Home'
    }
</script>

HelloWorld.vue

<template>
  <div id="app">
    <h1>我是HelloWorld组件</h1>
    <div class="nav">
      <router-link to="/home">Home</router-link>
      <router-link to="/about">About</router-link>
    </div>
    <div class="content">
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
  export default {
    name: 'HelloWorld'
  }
</script>

<style scoped>
  .content {
    background-color: skyblue;
  }
</style>

效果:

Vue-router 使用教程

/>

4. 命名路由

定义路由时,可以看见不仅定义了路径,同时还定义了名称,所以导航也可以指定为路由的名称。

使用方式如下:

<router-link to="/home">Home</router-link>
<!-- 等价于 -->
<router-link :to="{ path: '/home' }">Home</router-link>
<!-- 如果 /home 对应的名称为 home -->
<router-link :to="{ name: 'home' }">Home</router-link>

5. 路由传参

5.1 动态路由参数

使用动态路由参数,可以在路由路径中包含参数,这些参数可以在路由组件中通过 $route.params来获取。

路由定义:

const router = new VueRouter({
    routes: [{
        path: '/home',
        name: 'home',
        component: Home
    }, {
        path: '/about/:id',
        name: 'about',
        component: About
    }]
});

路由链接:

<router-link to="/about/123">About</router-link>

About 组件中,可以通过如下方式获取参数:

let id = this.$route.params.id

5.2 Props传参

可以通过路由配置中的 props 选项,将路由组件需要的参数直接作为 props 传递给组件。这种方式需要将 $route 对象的内容直接传递给组件,可以在组件中像普通 props 一样访问这些参数。

路由定义:

const router = new VueRouter({
    routes: [{
        path: '/home',
        name: 'home',
        component: Home
    }, {
        path: '/about/:id',
        name: 'about',
        props: true
        component: About
    }]
});

路由链接:

<router-link to="/about/123">About</router-link>

About 组件中,可以通过如下方式获取参数:

props: [ 'id'],

5.3 查询参数

通过查询参数传递数据,参数会出现在URL中的 ? 后面,并且可以通过 $route.query 来获取。

路由定义:

const router = new VueRouter({
    routes: [{
        path: '/home',
        name: 'home',
        component: Home
    }, {
        path: '/about',
        name: 'about',
        component: About
    }]
});

路由链接:

<router-link :to="{ path: '/about', query: { id: 123 }}">About</router-link>

About 组件中,可以通过如下方式获取参数:

let id = this.$route.query.id

5.4 通过导航钩子传参

...

6. 重定向和别名

6.1 重定向

例如增加一个 / 的路由,访问该路径默认会跳转到 home 路由。

const router = new VueRouter({
    routes: [{
        path: '/',
        redirect: { name: 'home' },
        //redirect: { path: '/home' }
    },{
        path: '/home',
        name: 'home',
        component: Home
    }, {
        path: '/about',
        name: 'about',
        component: About
    }]
});

甚至是一个方法,动态返回重定向目标:

const router = new VueRouter({
    routes: [{
        path: '/test/:id',
        redirect:  to => {
            // 访问 /test/100 => /home?id=100
            return { path: '/home', query: { id: to.params.id } }
        }
    },{
        path: '/home',
        name: 'home',
        component: Home,
        children: [
            { path: 'foo', component: Foo },
            { path: 'bar', component: Bar }
        ]
    }, {
        path: '/about',
        name: 'about',
        component: About
    }]
});

在写 redirect 的时候,可以省略 component 配置,因为它从来没有被直接访问过,所以没有组件要渲染。唯一的例外是嵌套路由。如果一个路由记录有 childrenredirect 属性,它也应该有 component 属性。

6.2 别名

上述例子中,重定向 / 路由会导致浏览器 url 发生改变 /home。但是可以使用重命名,访问 / 时,浏览器 url 不发生改变,但页面内容仍然是和 /home 路由一样的内容。

const router = new VueRouter({
    routes: [{
        path: '/home',
        name: 'home',
        alias: "/",
        component: Home
    }, {
        path: '/about',
        name: 'about',
        component: About
    }]
});

通过别名,可以自由地将 UI 结构映射到一个任意的 URL,而不受配置的嵌套结构的限制。使别名以 / 开头,以使嵌套路径中的路径成为绝对路径。甚至可以将两者结合起来,用一个数组提供多个别名。

7. 历史记录模式

历史记录模式分为两种:

  • hash 模式。特定是有#,SEO 效果差,适用于后台管理系统。
  • history 模式。和传统url类似,适合需要搜索引擎收录的网站。

之前创建的 VueRouter 实例,默认都是 hash 模式。所以都是带 # 的。

如果需要修改为 history 模式,指定 mode 即可。

const router = new VueRouter({
    //mode: 'hash',
    mode: 'history',
    routes: [{
        path: '/home',
        name: 'home',
        alias: "/",
        component: Home
    }, {
        path: '/about',
        name: 'about',
        component: About
    }]
});

8. 编程式导航

除了使用 创建 a 标签来定义导航链接,还可以借助 router 的实例方法,通过编写代码来实现。并且需要注意的是,开发中更多的是使用的编程式导航。

在组件中可以使用 this 对象,拿到 router 实例,然后调用 router 的 api 进行路由的修改。(这里修改的其实就是浏览器的地址)

  1. 使用 $router.push(location):导航到一个新的 URL,可以是一个字符串路径或一个描述地址的对象。例如:
// 字符串路径
this.$router.push('/home')

// 对象
this.$router.push({ path: '/home' })

// 带查询参数
this.$router.push({ path: '/home', query: { key: 'value' } })
  1. 使用 $router.replace(location):类似 $router.push(),但是不会在导航历史记录中留下记录,所以点击后退按钮无法返回上一个页面。用法与 $router.push() 相同。

  2. 使用 $router.go(n):在导航历史记录中向前或向后移动多少步。例如:

// 后退一步
this.$router.go(-1)

// 前进一步
this.$router.go(1)
  1. 使用 $router.back()$router.forward():分别用于后退和前进。这两种方式相当于 $router.go(-1)$router.go(1)。例如:
// 后退
this.$router.back()

// 前进
this.$router.forward()

这些方法可以需求选择使用,比如根据用户的操作进行页面导航、处理表单提交后的页面跳转等。

9. 导航守卫

导航守卫是 Vue Router 提供的一种机制,用于在路由导航过程中进行拦截和控制。它允许你在路由导航发生前、发生时、发生后等不同的阶段执行一些自定义逻辑。Vue Router 提供了全局导航守卫、路由独享守卫和组件内的守卫。

9.1 全局导航守卫

全局导航守卫包括 beforeEachbeforeResolveafterEach,它们分别在路由导航之前、导航被确认之前、导航成功完成之后触发。这些守卫可以在 Vue Router 实例上直接设置:

const router = new VueRouter({ ... });

router.beforeEach((to, from, next) => {
    console.log(" 在路由导航之前执行的逻辑");
});

router.beforeResolve((to, from, next) => {
    console.log("在导航被确认之前执行的逻辑");
});

router.afterEach((to, from) => {
    console.log("在导航成功完成之后执行的逻辑");
});

以上 beforeEachbeforeResolve 均可以使用 next(false) 来终端导航,并且如果导航没问题,必须使用 next() 放行。

9.2 路由独享守卫

路由独享守卫是针对某个特定路由设置的守卫,通过在路由配置中使用 beforeEnter 字段来定义:

const router = new VueRouter({
    //mode: 'hash',
    mode: 'history',
    routes: [{
        path: '/home',
        name: 'home',
        component: Home,
        beforeEnter: (to, from, next) => {
            // 在进入 '/foo' 路由之前执行的逻辑
        }
    }, {
        path: '/about',
        name: 'about',
        component: About
    }]
});

9.3 组件内的守卫

组件内的守卫包括 beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave,它们分别在组件被创建、更新和销毁时触发。

export default {
    name: 'Home',
    beforeRouteEnter(to, from, next) {
        // 注意:在这里无法通过 this 访问组件实例,因为组件还未被创建
        console.log("在进入该组件路由之前执行的逻辑");
        next();
    },
    beforeRouteUpdate(to, from, next) {
        // 可以访问组件实例
        console.log("在当前路由改变,但是该组件被复用时执行的逻辑");
        next();
    },
    beforeRouteLeave(to, from, next) {
        // 在离开该组件的路由时执行的逻辑
        console.log("在离开该组件的路由时执行的逻辑");
        next();
    }
}

提醒:本文发布于123天前,文中所关联的信息可能已发生改变,请知悉!

Tips:清朝云网络工作室

阅读剩余
THE END