vue-router

vue-router 是什么?它的作用是什么?

是Vue.js官方提供的一个插件,用于实现前端路由功能

是SPA(单页应用)的路径管理器,使得用户在浏览器中切换页面时,不需要重新加载整个页面,而只是更新部分内容,从而提供更流畅的用户体验。

主要作用包括:

  1. 路由映射: 可以通过定义路由规则来将不同的URL路径映射到相应的组件上。当用户访问特定的URL时,Vue Router会根据路由规则选择并加载对应的组件

  2. 嵌套路由: 在一个组件中定义子路由,从而实现更复杂的页面结构。这样可以方便管理和组织你的页面结构,提高代码复用性。

  3. 路由传参: 通过URL路径、查询参数或者路由配置中的属性进行传递。这样可以方便地实现动态路由和组件间的数据传递。

  4. 导航守卫: Vue Router提供了多种导航守卫(Navigation Guards)的机制,用于在路由导航过程中进行拦截和控制。你可以使用导航守卫来验证用户的登录状态、权限验证、页面切换动画等。

在Vue中使用Vue Router

参考

安装Vue Router:

npm install vue-router --save

创建路由实例:

src/router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

// 创建 router 实例
const router = new VueRouter({
  routes: [
    // 在这里定义你的路由规则
  ]
})

export default router

设置路由规则:

每个路由规则都包含一个路径(path)和对应的组件(component):

import Home from '../view/home/Home.vue';
const About = { template: '<div>about</div>' }

const router = new VueRouter({
  routes: [
    {
      path: '/',
      // "component" 可以是:
      // 1. 通过 `Vue.extend()` 创建的组件构造器
      // 2. 组件配置对象
      // 3. vue组件
      component: Home // 在这里替换成你的首页组件
    },
    {
      path: '/about',
      component: About // 在这里替换成你的关于页面组件
    },
    // 添加更多的路由规则...
  ]
})

挂载到Vue实例中:

import Vue from 'vue'
import router from './router' // 引入上述创建的路由实例

new Vue({
  router, // 配置路由实例
  // 其他配置项...
}).$mount('#app')

在模板中使用路由:

在你的Vue组件的模板中,使用<router-link>组件来生成路由链接,使用<router-view>组件来展示对应的组件内容。示例代码如下:

<template>
  <div>
    <!-- router-link 声明式导航跳转 -->
    <router-link to="/">Home</router-link>
    <router-link to="/about">About</router-link>
    <!-- 添加更多的路由链接... -->
  
    <!-- router-view 路由出口:路由匹配到的组件将渲染在这里 -->
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  computed: {
    username() {
      // 在任何组件内通过 `this.$route` 访问当前路由
      // 我们很快就会看到 `params` 是什么
      return this.$route.params.username;
    },
  },
  methods: {
    goBack() {
      // 在任何组件内通过 `this.$router` 访问路由实例
      window.history.length > 1
        ? this.$router.go(-1)
        : this.$router.push("/");
    },
  },
};
</script>

核心组件是哪些?

RouterView路由视图<router-view>标签,用于显示匹配到的路由组件内容的占位符组件。

RouterLink<router-link>标签,用于创建到指定路由的超链接组件。当点击时会改变URL并进行导航,而不是进行全页刷新

  • 结合RouterLinkActive:常用于为激活的导航链接添加样式

    • 当前激活的路由链接会添加一个特定的类名router-link-active

    • 可通过 active-class 来修改默认的 router-link-active 类名

      <router-link to="/some-route" active-class="custom-active-class">Some Route</router-link>
      

router 和 route 的区别

router:Vue Router的主要实例,用于管理路由规则和导航。因此你可以调用 this.$router.push**

route路由记录对象,表示当前激活的路由状态信息,包含了当前 URL 解析得到的信息,还有 URL 匹配到的路由记录 (route records)。可以通过$route属性访问当前路由对象的信息,如路由参数、查询参数等。

状态信息:

  • fullpath
  • path
  • params
  • query
  • hash
  • meta

导航守卫(NavigationGuard)

全局路由守卫

beforeEach

beforeEach(to, from, next):前置守卫

  • to :即将要进入的目标路由对象

  • from:当前正要离开的路由对象

  • next:路由控制参数

    • next():如果一切正常,则调用这个方法进入下一个钩子

    • next(false):取消导航(即路由不发生改变)

    • next('/login'):当前导航被中断,然后进行一个新的导航

    • next(error):如果一个 Error 实例,则导航会被终止且该错误会被传递给

作用:

  • 鉴权验证(身份、登录、页面访问权限 等)

  • 重定向

  • 修改网页title

    router.beforeEach((to, from) => {
      document.title = to.meta.title;
    });
    
  • 监听错误 NavigationFailure:

    • 导航失败的事件和相关信息:

      • 错误消息:描述导航失败的原因。
      • 错误代码:用于标识特定类型的导航错误。
      • 原始错误对象:包含有关错误的更多详细信息。
    • 示例:

      router.beforeEach((to, from, next) => {
        try {
          // 尝试进行路由跳转
          next();
        } catch (error) {
          if (error instanceof NavigationFailure) {
            // 处理导航失败的情况
            console.error('导航失败:', error.message);
            // 可以在这里执行其他操作,如显示错误消息给用户等
          } else {
            // 处理其他类型的错误
            console.error('发生未知错误:', error);
          }
        }
      });
      
afterEach

afterEach(to, from):后置守卫

作用:当前页面的记录日志(Sentry、LogRocket),并将信息发送到服务器进行分析用户行为

  • Sentry:错误跟踪工具
    • 错误监控:它能够实时监控应用程序的异常和错误日志,帮助开发者快速发现并解决问题。
    • 多语言支持:Sentry支持多种编程语言和框架,这使得它可以在不同的开发环境中使用。
    • 智能化分析:它提供智能化的错误分析,帮助开发者理解错误产生的原因,从而更有效地修复问题。
    • 集成平台:作为一个集成平台,Sentry提供了丰富的功能和灵活的配置选项,以满足不同项目的需求。
  • LogRocket:前端日志记录工具
    • 前端日志记录:LogRocket专注于前端,帮助开发者记录用户在Web应用中的操作,如点击、页面浏览等。
    • 用户行为分析:通过记录用户的交互行为,LogRocket可以辅助开发者了解用户如何使用应用,从而优化用户体验。
    • 性能监控:除了记录错误和用户行为,LogRocket还可以监控应用的性能,如加载时间和运行时错误。
beforeResolve

beforeResolve:路由解析

路由独享守卫:beforeEnter

beforeEnter(to, from, next):通常用于处理特定路由的需求,如加载数据、处理权限等

const router = new VueRouter({
  routes: [
    {
      path: '/admin',
      name: 'Admin'
      component: () => import(/* webpackChunkName: "Admin" */ '../views/Admin.vue'),
      beforeEnter: (to, from, next) => {
        if (isLogin) {
          return next()
        }
  			return next('/login?redirect' = to.fullpath)
      },
      // beforeEnter: (route) => {  }
    }
  ]
})

组件内路由守卫

beforeRouteEnter

beforeRouteEnter(to, from, next):在导航确认前被调用

注意:

  • 新组件还没被创建。所以不能获取实例(this)

  • 可以通过传一个回调给 next 来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。

    beforeRouteEnter 是支持给 next 传递回调的唯一守卫。对于 beforeRouteUpdatebeforeRouteLeave 来说,this 已经可用了,所以不支持传递回调,因为没有必要了。

export default {
  beforeRouteEnter(to, from, next) {
    // 在渲染该组件的对应路由被确认前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建

    next((vm) => {
      // 通过 `vm` 访问组件实例
    });
  },
};

示例: 判断进入页面后的访问内容

export default {
  data() {
    return {
      code: 1, // 步骤
    };
  },
  beforeRouteEnter(to, from, next) {
    // 从详情页进来
    if (from.name == "detail") {
      return next((vm) => {
        vm.getDetail(2);
      });
    }
    
    next();
  },
  methods: {
    // 获取详情
    getDetail(id) {
      this.code = id;
    },
  },
};
beforeRouteUpdate

beforeRouteUpdate(to, from, next)

作用:常用于监听路由变化

export default {
  beforeRouteUpdate(to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。

    // 可以访问组件实例 `this`
    this.name = to.params.name;
    next();
  },
};
beforeRouteLeave

beforeRouteLeave(to, from, next)

常用于:

  • 禁止用户在还未保存修改前突然离开 / 离开页面前提示用户还有数据未保存
export default {
  beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
    const answer = window.confirm(
      "Do you really want to leave? you have unsaved changes!"
    );
    if (answer) {
      next();
    } else {
      next(false); // 通过 `next(false)` 来取消路由跳转
    }
  },
};

完整的导航解析流程

  • 点击导航被触发。

  • 失活路由组件内触发 beforeRouteLeave 守卫。

  • 触发 全局路由守卫 beforeEach

  • (判断):

    • 重用路由组件内触发 beforeRouteUpdate 守卫 (2.2+)。

    • 非重用路由配置中,触发路由独享守卫 beforeEnter

      • 解析异步路由组件。

      • 在被激活的路由组件内触发 beforeRouteEnter

      • 触发 全局路由守卫 beforeResolve 守卫 (2.5+)。

      • 导航被确认。

      • 触发 全局路由守卫 afterEach

      • 触发 DOM 更新。

      • (判断)调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

编程导航(路由跳转)方式

Vue Router 的导航方法 (push、 replace、 go) 在各类路由模式 (history、 hash 和 abstract) 下表现一致

声明式:<router-link>

<router-link> 组件。

生成带有导航链接可点击元素,默认会被渲染成一个 <a> 标签。

设置组件的 to 属性来指定目标路由路径,并可以使用其他属性来配置导航行为

<router-link> 对应的路由匹配成功,将自动设置 class 属性值 .router-link-active

<!-- 通过传入 `to` 属性指定目标路由路径。对应编程式的 `router.push` -->
<router-link to="/foo">Go to Foo</router-link>
<!-- 设置组件的 `replace` 属性。对应编程式的 router.replace -->
<router-link to="xx" replace>Go to Foo</router-link>

router.push

router.push(location[, onComponent, onAbort]) 跳转指定地址,并添加到历史记录中。

会向 history 栈添加一个新的记录。所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

类似 window.history.pushState

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

参数:

  • location 要跳转的地址。可以是一个字符串路径,或者一个描述地址的对象

    // 字符串
    router.push("detail");
    router.push("/detail");
    
    // 一个描述地址的对象
    router.push({ name: "detail" });
    
    // 命名的路由:/detail/12
    router.push({ name: "detail", param: { id: "12" } });
    
    // 注意:如果提供了 path,params 会被忽略
    // 同样的规则也适用于 `router-link` 组件的 `to` 属性。
    router.push({ path: '/detail', params: { id: '12' } }) // -> /detail
    
    // 带查询参数:/detail?id=12
    router.push({ name: "detail", query: { id: "12" } });
    

可选参数:

  • onComponent 结束的回调

  • onAbort 取消的回调

在 2.2.0+,可选的在 router.pushrouter.replace 中提供 onCompleteonAbort 回调作为第二个和第三个参数。这些回调将会在导航成功完成 (在所有的异步钩子被解析之后) 或终止 (导航到相同的路由、或在当前导航完成之前导航到另一个不同的路由) 的时候进行相应的调用。

在 3.1.0+,可以省略第二个和第三个参数,此时如果支持 Promise,router.pushrouter.replace 将返回一个 Promise。

router.replace

router.replace(location[, onComponent, onAbort]) 用指定的路由替换当前路由。

router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录

类似 window.history.replaceState

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

参数:

  • location 要跳转的地址。可以是一个字符串路径,或者一个描述地址的对象

可选参数:

  • onComponent 结束的回调

  • onAbort 取消的回调

router.go

router.go(n) 在历史记录中向前或向后移动 N 步。

类似 window.history.go(n)

参数:

  • 没有参数: 前进一页,等价于 router.go(1)

  • n 整数,意思是在 history 记录中向前或者后退多少步

    • 0: 刷新当前页面
    • 正整数: 前进几页
    • 负整数: 后退几页
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1);

// 后退一步记录,等同于 history.back()
router.go(-1);

// 前进 3 步记录
router.go(3);

// 如果 history 记录不够用,那就默默地失败呗
router.go(-100);
router.go(100);

router.back

等同于this.$router.go(-1),后退到上一个访问的路由。

类似 window.history.back()

router.forward

等同于this.$router.go(1),前进到下一个路由。

类似 window.history.forward()

router.resolve

router.resolve: 用于解析路由的匹配结果。

参数:

  • location:要解析的 URL 地址或路由对象。

  • callback:一个回调函数,用于处理解析结果。

    • result 包含解析结果对象
      • location:解析后的 URL 地址或路由对象。
      • route:与解析结果匹配的路由对象。
      • params:解析结果中的动态路由参数。
      • query:解析结果中的查询参数。
      • fullPath:解析结果的完整路径。
      • hash:解析结果的哈希值(如果存在)。
      • matched:与解析结果匹配的路由记录数组。
      • instances:包含所有匹配路由组件实例的数组。

示例:

// 假设有一个路由配置如下:
// { path: '/user/:id', component: User, props: true }

// 解析 URL 地址为 /user/123 的路由
const resolved = router.resolve({ path: '/user/123' }, (result) => {
  console.log(result.route); // 打印匹配的路由对象
  console.log(result.params); // 打印动态路由参数 { id: '123' }
  console.log(result.query); // 打印查询参数 {}
  console.log(result.fullPath); // 打印完整路径 '/user/123'
});

router.currentRoute

router.currentRoute: 获取当前路由信息

路由重定向

redirect 直接重定向到指定路由

在路由配置中通过redirect字段直接将一个路由重定向到指定路径

const router = new VueRouter({
  routes: [
    {
      path: '/home',
      component: Home
    },
    {
      path: '/about',
      redirect: '/home' // 将/about重定向到/home
    }
  ]
})

redirect 命名路由重定向

const router = new VueRouter({
  routes: [
    {
      path: '/home',
      name: 'home', // 必须要有name,才能支持 name 重定向
      component: Home
    },
    {
      path: '/about',
      redirect: { name: 'home' } // 重定向到命名为'home'的路由
    }
  ]
})

redirect 动态重定向

使用函数的方式,可以实现更灵活的重定向配置。该函数会接收当前路由对象作为参数,并返回一个重定向的路径

const router = new VueRouter({
  routes: [
    {
      path: '/users/:id',
      component: User,
      redirect: to => {
        // 当用户访问`/users/:id`时,根据`:id`参数值动态决定重定向到不同的路径。
        // 如果`id`为`admin`,则重定向到`/admin`路径,否则重定向到`/users/:id`路径
        const { id } = to.params
        
        if (id === 'admin') {
          return '/admin'
        }
        return `/users/${id}`
      }
    }
  ]
})

路由传参

params:动态路径,URL路径参数 /user/detail/1

URL路径参数,将参数直接嵌入到URL路径。

参数: object

常用于: 跳转详情页

使用:

1、定义路由规则:

const router = new VueRouter({
  routes: [
    {
      // 带有动态路由参数的路由规则
      // 路由匹配:可以匹配任意非斜杠字符
      // 写法:使用冒号(:)标记参数,参数名将作为一个占位符来接收实际的值
      path: '/user/detail/:id', // 参数名为 id
      // path: '/user/detail/:id(\\d+)", // 正则匹配 id 必须是数字
      // path: '/user/detail/:id/:other", // 根据实际需求定义多个动态路由参数
      component: User,
    }
  ]
})

/user/detail/:id 表示定义一个路径片段(dynamic segments)。当访问/user/detail/1时,路由会匹配到该规则,并将实际的参数值传递给User组件

2、路由跳转:

this.$router.push('/user/detail/1')

注意:如果传入的是对象,path 优先级高于 params ,所以params 会被忽略

this.$router.push({ path: '/user/detail/1' })

this.$router.push({ path: '/user/detail', params:{ id: 1 } }) // 无效路由跳转

// 可以将path改成name
this.$router.push({
	name:'User',
	params:{ id: 1 }
})

3、访问 params 参数:

// 路由匹配时,这些路径参数会被提取,并可以通过`$route.params`对象进行访问
// id 为路由规则定义的参数名
this.$route.params.id;

query:查询参数 /user/detail?id=1

查询参数,将参数作为URL的查询字符串(query string)的一部分进行传递的方式

参数: object

常用于: 存放需要与后端交互的参数

使用:

1、路由跳转:

this.$router.push({ path: '/user/detail', query: { id: 1 }})

2、访问 query 参数:

this.$route.query.id;

hash:/user/detail#step=1

hash 值

url上显示形式:

  • /user/detail#step=1
  • /user/detail?id=1#step=1
  • /user/detail?id=1#step=1&other=xxx

参数: string

常用于: 存放网页需要处理参数

使用:

1、路由跳转:

this.$router.push({ path: '/user/detail', hash: "#step=1" })
this.$router.push({ path: '/user/detail', query: {}, hash: "#step=1&other=xxx" })
this.$router.push({ path: '/user/detail', hash: "#step=1&other=xxx" })

2、访问 hash 参数:

this.$route.hash; // "#step=1&other=xxx"

meta:路由配置中的属性

路由配置中通过自定义的属性来传递数据。

使用:

1、定义路由规则:

const router = new VueRouter({
  routes: [
    {
      path: '/user/detail',
      component: User,
      meta: { id: 1 }, // 自定义属性
    }
  ]
})

2、访问 meta 属性:

this.$route.meta.id

paramsquery 两者区别

  • query 相当于 get 请求,页面跳转的时候,可以在地址栏看到请求参数;params 相当于 post 请求,参数不会再地址栏中显示
  • params是路由的一部分,必须要在路由后面添加参数名query是拼接在url后面的参数,没有也没关系
  • params 一旦设置在路由,params 就是路由的一部分,如果这个路由有 params 传参,但是在跳转的时候没有传这个参数,会导致跳转失败或者页面会没有内容

动态添加路由 V2.2.0+

先明确不是动态路径,而是动态添加路由。

通过动态添加路由 router.addRoutes(routes) 方法 来实现根据特定条件或动态数据生成路由的功能。

思路:

  • 首先创建了一个初始的Vue Router实例,并定义了一些静态的路由规则
  • 将获取到的动态路由,通过router.addRoutes(routes)方法来动态添加路由。routes参数是一个包含新路由配置对象的数组。

动态路由数据:

  • 根据后台返回的数据生成路由
  • 根据用户权限动态展示的路由
const router = new VueRouter({
  routes: [
    // 初始的静态路由配置
    {
      path: '/',
      component: Home,
    },
    {
      path: '/about',
      component: About,
    }
  ]
})

// 动态添加路由
const trendRoutes = [
  {
    path: '/products',
    component: Products,
  },
  {
    path: '/contact',
    component: Contact,
  }
]
router.addRoutes(trendRoutes)

路由嵌套(嵌套路由)

在Vue Router中,可以通过配置嵌套路由来实现路由的嵌套结构。嵌套路由可用于在父路由下定义子路由,实现页面的嵌套和组件的层级关系。以下是一个使用嵌套路由的示例:

const router = new VueRouter({
  routes: [
    {
      path: '/dashboard',
      component: Dashboard,
      children: [
        {
          // 以 / 开头的嵌套路径会被当作根路径
          // 这让你充分的使用嵌套组件而无须设置嵌套的路径
      		// path: '/dashboard/overview',
          
          // 或者使用如下,不添加/,默认拼接成 /dashboard/overview
          path: 'overview',
          
          // 当 /dashboard/overview 匹配成功
          // Overview 会被渲染在 Dashboard 的 <router-view> 中
          component: Overview
        },
        {
          path: 'settings',
          component: Settings
        }
      ]
    }
  ]
})

在上述示例中,Dashboard是一个父级路由,它定义了两个子路由:OverviewSettings。父级路由的路径是/dashboard,而子路由的路径是相对于父级路由的,分别是/dashboard/overview/dashboard/settings

在创建嵌套路由时,需要注意以下几点:

  1. 在父级路由的组件中使用<router-view>标签来作为子组件的占位符,用于渲染子路由对应的组件。
  2. 子路由的 path 配置是相对于父级路由的,可以使用相对路径或绝对路径。
  3. 子路由配置应该放在父路由的 children 属性中。
  4. 嵌套路由可以继续嵌套,形成更深层次的路由结构。

在使用嵌套路由时,可以根据实际需求设置不同的层级关系和嵌套结构,从而构建复杂的页面布局和导航逻辑。在父级路由的组件模板中使用<router-view>标签,将会根据当前路由的路径动态渲染匹配的子路由组件。

路由懒加载(延迟加载或按需加载)

单页面应用(SPA)中,如果不使用懒加载,那么应用的所有资源包括JavaScript、CSS和HTML都会在首次进入时一次性加载,这会导致首页加载时间过长,影响用户体验。

为了解决首屏加载这个问题,Vue Router提供了懒加载的功能。

component: () => import(/* webpackChunkName: 'about' */ './views/About.vue') 

作用: 只有当用户访问到(需要)某个路由时,相关的组件才会被加载,而不是一开始就加载所有的路由组件。

优点:

  • 提高首屏加载速度
    • 减少初始加载时的资源体积(组件、图片等各种资源)
    • 减少初始加载时的网络请求次数
    • 减少内存占用,提高应用的整体性能
  • 优化用户体验:懒加载可以让用户在不牺牲太多性能的情况下,快速看到首页的内容,而在用户进一步探索应用时,其他路由的组件才会被加载。

使用: 路由配置文件

const router = new VueRouter({
  routes: [
    {
      path: '/about',
      // 使用动态导入延迟加载组件   
      component: () => import(/* webpackChunkName: 'about' */ './views/About.vue') 
    },
    // 其他路由规则...
  ]
})

import()函数动态导入语法: 是实现 组件异步加载/延迟加载 关键语法,代替直接引入组件。当用户导航到某个路由时(路由被访问时),对应的组件才会被异步加载并渲染。

webpackChunkName 结合Webpack的代码分割功能,定义 import()webpackChunkName 将模块分割成不同的代码块。可以将每个路由对应的组件打包成一个单独的文件,只有在该路由被访问时才会加载对应的文件。

注意:

  • 懒加载只适用于异步加载的路由组件。对于常规(同步)加载的组件,不需要使用懒加载机制。
  • 对于小型应用或页面数量较少的应用,懒加载可能带来的性能优势可能不太明显
  • 如果所有的路由组件 webpackChunkName 一样,则定义异步加载组件的优势没有体现出来

路由的404页面

通配符路由/捕获所有路由

在路由配置中定义一个通配符路由,用于匹配所有未被定义的路由路径。将该通配符路由配置映射到 404的页面组件。当用户访问一个不存在的路径时,通配符路由就会被激活并匹配到,然后会渲染NotFound组件,即404页面

const router = new VueRouter({
  routes: [
    // 其他路由配置...
    {
      // 会匹配以 `/user-` 开头的任意路径
      path: "/user-*";
    },
    {
      path: '*', // 表示该路由会匹配所有未被定义的路径
      component: NotFound, // 显示404页面的组件
    }
  ]
})

注意:

  • 使用通配符路由时,请确保路由的顺序是正确的。含有通配符的路由应该放在最后。
  • 如果你使用了History 模式,请确保 正确配置你的服务器

当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:

// 给出一个路由 { path: '/user-*' }
this.$router.push("/user-admin");
this.$route.params.pathMatch; // 'admin'

// 给出一个路由 { path: '*' }
this.$router.push("/non-existing");
this.$route.params.pathMatch; // '/non-existing'

导航守卫

在全局路由守卫 beforeEach 中处理路由的404页面。检查要跳转的路由是否存在,如果不存在则跳转到404页面。

router.beforeEach((to, from, next) => {
  if (router.hasRoute(to.name)) {
    // 路由存在,继续跳转
    next()
  } else {
    // 路由不存在,跳转到404页面
    next({ path: '/404' })
  }
})

监听路由变化

当使用路由参数时,例如从 /detail/1 导航到 /detail/2原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用

watch

复用组件时,想对路由参数的变化作出响应的话,你可以简单地使用 watch 监听 $route 对象:

浅响应
const User = {
  template: '<div>...</div>',
  watch: {
    $route(to, from) {
      // 对路由变化做出响应
      // to , from 分别表示从哪跳转到哪,都是一个对象
      // to.path   ( 表示的是要跳转到的路由的地址 eg:  /home );
      console.log('当前路由', to, '上一个路由', from)
    }
  }
}
深响应
const User = {
  template: '<div>...</div>',
  watch: {
    "$route.params.login": {
      deep: true, // 深层监听
      immediate: true, // 立即执行回调函数
      // 数据发生变化时执行回调函数
      handler (to, from) { }
    }
  }
}
监听特定的值
const User = {
  template: '<div>...</div>',
  watch: {
    "$route.params.login": function (to, from) {},
  }
}

beforeRouteUpdate

使用 2.2 中引入的 beforeRouteUpdate 导航守卫

const User = {
  template: '...',
  beforeRouteUpdate(to, from, next) {
    // react to route changes...
    // don't forget to call next()
  }
}

路由模式

Vue2Vue3
historycreateWebHistory
hashcreateWebHashHistory
abstactcreateMemoryHistory

hash

hash 是 URL 中 hash(#)及后面的那部分,例如http://example.com/page#section1

常用作锚点在页面内进行导航,改变 URL 中的hash部分不会引起页面刷新。

通过监听 hashchange 事件来响应哈希的变化。改变URL的方式只要这几种:

  • 通过浏览器前进后退改变URL
  • 通过 a 标签改变URL
  • 通过 window.location 改变URL

history

history 提供了 pushState()replaceState() 两个方法,这两个方法改变URL 的 path 部分,不会引起页面刷新

通过监听 popstate 事件来响应历史记录的变化

  • 通过浏览器前进后退改变URL时,会触发 popstate 事件
  • 通过 pushState()replaceState() 、a 标签来改变URL时,不会触发 popstate 事件
    • 可以拦截 pushState()replaceState() 的调用和 a 标签的点击事件来检测 URL 变化
  • 通过js调用 history 的 back、go、forward 方法可触发该事件

hash 和 history 的区别

哈希(Hash)和历史记录(History)是Web开发中常用的两种管理页面状态和导航的方式,它们有一些明显的区别:

表现不同:

  • 原理不同:

    • hash 通过监听 hashchange 事件来响应哈希的变化
    • history 通过监听 popstate 事件来响应历史记录的变化
  • url不同: history 没有符号标识,看上去更加优雅、简洁

  • 服务端: hash 不会触发服务端的请求;History 会触发服务端请求

  • 部署: history部署的时候需要特殊配置,web服务器需要做回退处理,否则会出现刷新页面 404 的问题

兼容性: 由于 history 是 H5 新特性,兼容 IE >= 10 以上浏览器;hash能兼容ie8

使用: 在Vue中使用上是一样的

在这里插入图片描述

Nginx 配置 history 模式

在这里插入图片描述

try_files 解读:

  • $uri:尝试找文件
  • $uri/:尝试找地址
  • /admin/index.html:前面两种方式都找不到,回退到 主页 index.html
  • 13
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值