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

概念

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

安装方式

使用CDN

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

使用npm

$ npm install vue-router@4

使用yarn

$ yarn add vue-router@4

基础

routerlinkrouterview

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

router-link

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

router-view

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

<p>
    <!--使用 router-link 组件进行导航 --&gt;
    <!--通过传递 `to`指定链接 --&gt;
    <!--`<router-link&gt;`呈现一个带有正确 `href` 属性<a&gt;标签--&gt;
    <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。这有以下优点:

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

const router = createRouter({ ... })
router.beforeEach((to, from) => {
  // ...
  // 返回 false取消导航
  return false})

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

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

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

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 守卫 只在进入路由时触发,不会在 paramsqueryhash 改变时触发。

数据获取

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

<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()
    }
  },}

原文地址:https://blog.csdn.net/weixin_46282323/article/details/134698461

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_10225.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注