vue ——Vue-router

概念

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

  • 嵌套路由映射
  • 动态路由选择
  • 模块化、基于组件的路由配置
  • 路由参数、查询、通配符
  • 展示由 Vue.js 的过渡系统提供的过渡效果
  • 细致的导航控制
  • 自动激活 CSS 类的链接
  • HTML5 history 模式或 hash 模式
  • 可定制的滚动行为
  • URL 的正确编码

安装方式

使用CDN

<script src="https://unpkg.com/vue-router@4"></script>

使用npm

$ npm install vue-router@4

使用yarn

$ yarn add vue-router@4

基础

router-link 与 router-view

用 Vue + Vue Router 创建单页应用非常简单:通过 Vue.js,我们已经用组件组成了我们的应用。当加入 Vue Router 时,我们需要做的就是将我们的组件映射到路由上,让 Vue Router 知道在哪里渲染它们。

router-link

router-link来创建链接,他的作用相当于html的a标签。这使得 Vue Router可以在不重新加载页面的情况下更改 URL,处理 URL 的生成以及编码。

router-view

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

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

带参数的动态路由匹配

很多时候,我们需要将给定匹配模式的路由映射到同一个组件。例如,我们可能有一个 User 组件,它应该对所有用户进行渲染,但用户 ID 不同。在 Vue Router 中,我们可以在路径中使用一个动态字段来实现,我们称之为路径参数
路径参数用冒号:表示。当一个路由被匹配时,它的 params 的值将在每个组件中以 this.$route.params的形式暴露出来

 { path: '/users/:id', component: User }

在users这个页面中,你可以使用$route.params.id来获取传输过来的数据。

编程式导航

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

router.push()方法会向 history 栈添加一个新的记录
router.push('/users/eduardo')
router.replace()方法替换当前的位置
router.replace({ path: '/home' })
router.push({ path: '/home', replace: true })
router.go(number)

表示在历史堆栈中前进或后退多少步。

命名路由

除了 path 之外,你还可以为任何路由提供 name。这有以下优点:

  • 没有硬编码的 URL
  • params 的自动编码/解码。
  • 防止你在 url 中出现打字错误。
  • 绕过路径排序(如显示一个)
const routes = [
  {
    path: '/user/:username',
    name: 'user',
    component: User,
  },]

重定向和别名

重定向重定向是指当用户访问 /home 时,URL 会被 / 替换,然后匹配成 /,也是通过 routes 配置来完成,下面例子是从 /home 重定向到 /:

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

将 / 别名为 /home,意味着当用户访问 /home 时,URL 仍然是 /home,但会被匹配为用户正在访问 /
const routes = [{ path: ‘/’, component: Homepage, alias: ‘/home’ }]

不同的历史模式

在创建路由器实例时,history 配置允许我们在不同的历史模式中进行选择。
hash 模式是用 createWebHashHistory() 创建的:

import { createRouter, createWebHashHistory } from 'vue-router'
const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    //...
  ],})

它在内部传递的实际 URL之前使用了一个哈希字符(#)。由于这部分URL从未被发送到服务器,所以它不需要在服务器层面上进行任何特殊处理。不过,它在SEO中确实有不好的影响。如果你担心这个问题,可以使用 HTML5 模式
HTML5 模式是用 createWebHistory() 创建 ,推荐使用这个模式:

import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
  history: createWebHistory(),
  routes: [
    //...
  ],})

进阶

导航守卫

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

  • 全局前置守卫
    你可以使用 router.beforeEach 注册一个全局前置守卫:
const router = createRouter({ ... })
router.beforeEach((to, from) => {
  // ...
  // 返回 false 以取消导航
  return false})

当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中。
每个守卫方法接收两个参数:

to: 即将要进入的目标 用一种标准化的方式
from: 当前导航正要离开的路由 用一种标准化的方式

可以返回的值如下:
false: 取消当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
一个路由地址: 通过一个路由地址跳转到一个不同的地址,就像你调用 router.push() 一样,你可以设置诸如 replace: true 或 name: ‘home’ 之类的配置。当前的导航被中断,然后进行一个新的导航,就和 from 一样。
可选的第三个参数 next
在之前的 Vue Router 版本中,也是可以使用 第三个参数 next 的。这是一个常见的错误来源,可以通过 RFC 来消除错误。然而,它仍然是被支持的,这意味着你可以向任何导航守卫传递第三个参数。在这种情况下,确保 next 在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错

  • 全局解析守卫
    你可以用router.beforeResolve 注册一个全局守卫。
    这和 router.beforeEach 类似,因为它在 每次导航时都会触发,但是确保在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被正确调用。这里有一个例子,确保用户可以访问自定义 meta 属性 requiresCamera 的路由:
router.beforeResolve(async to => {
  if (to.meta.requiresCamera) {
    try {
      await askForCameraPermission()
    } catch (error) {
      if (error instanceof NotAllowedError) {
        // ... 处理错误,然后取消导航
        return false
      } else {
        // 意料之外的错误,取消导航并把错误传给全局处理器
        throw error
      }
    }
  }})

router.beforeResolve 是获取数据或执行任何其他操作(如果用户无法进入页面时你希望避免执行的操作)的理想位置。

  • 全局后置钩子
    你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:
router.afterEach((to, from) => {
  sendToAnalytics(to.fullPath)})
  • 路由独享守卫
    你可以直接在路由配置上定义 beforeEnter 守卫:
const routes = [
  {
    path: '/users/:id',
    component: UserDetails,
    beforeEnter: (to, from) => {
      // reject the navigation
      return false
    },
  },]

beforeEnter 守卫 只在进入路由时触发,不会在 params、query 或 hash 改变时触发。

数据获取

有时候,进入某个路由后,需要从服务器获取数据。例如,在渲染用户信息时,你需要从服务器获取用户的数据。我们可以通过两种方式来实现:

  • 导航完成之后获取
    先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示“加载中”之类的指示。
    假设我们有一个 Post 组件,需要基于 $route.params.id 获取文章数据:
<template>
  <div class="post">
    <div v-if="loading" class="loading">Loading...</div>
    <div v-if="error" class="error">{{ error }}</div>
    <div v-if="post" class="content">
      <h2>{{ post.title }}</h2>
      <p>{{ post.body }}</p>
    </div>
  </div></template>
export default {
  data() {
    return {
      loading: false,
      post: null,
      error: null,
    }
  },
  created() {
    // watch 路由的参数,以便再次获取数据
    this.$watch(
      () => this.$route.params,
      () => {
        this.fetchData()
      },
      // 组件创建完后获取数据,
      // 此时 data 已经被 observed 了
      { immediate: true }
    )
  },
  methods: {
    fetchData() {
      this.error = this.post = null
      this.loading = true
      // replace `getPost` with your data fetching util / API wrapper
      getPost(this.$route.params.id, (err, post) => {
        this.loading = false
        if (err) {
          this.error = err.toString()
        } else {
          this.post = post
        }
      })
    },
  },}
  • 导航完成之前获取
    导航完成前,在路由进入的守卫中获取数据,在数据获取成功后执行导航。
    可以在接下来的组件的 beforeRouteEnter 守卫中获取数据,当数据获取成功后只调用 next 方法
export default {
  data() {
    return {
      post: null,
      error: null,
    }
  },
  beforeRouteEnter(to, from, next) {
    getPost(to.params.id, (err, post) => {
      next(vm => vm.setData(err, post))
    })
  },
  // 路由改变前,组件就已经渲染完了
  // 逻辑稍稍不同
  async beforeRouteUpdate(to, from) {
    this.post = null
    try {
      this.post = await getPost(to.params.id)
    } catch (error) {
      this.error = error.toString()
    }
  },}

你可能感兴趣的:(vue.js,vue.js,前端,javascript)