Vue-5 路由传参的几种方式(query和params),获取路由参数,导航守卫和路由元信息,History模式
除了 props 和 $emit 之外,路由时也可以携带数据,即通过路由传参。
一、路由参数的传递和接收
1. 动态路由的匹配
示例需求:有个商品详情的组件,点击任何商品都会渲染这个组件,点击商品时向详情组件传递商品的 id,详情组件在被渲染时接收这个 id,请求对应的数据,渲染在详情组件上。
可以在配置路由时直接为参数预留路径:
// router>index.js 的routes
routes: [
{
// 在路径中预留参数的位置
path: '/good-detail/:id',
component: Detail
}
]
调用:
<!-- 调用路由时向路由传参 -->
<router-link to="/good-detail/1">商品1</router-link>
<router-link to="/good-detail/2">商品2</router-link>
<router-link to="/good-detail/3">商品3</router-link>
<!-- 渲染详情组件 -->
<router-view />
接收参数:
<!-- 详情组件的结构中接收 -->
<div class="detail">
<!-- 用 $route 获取路由信息,从路由信息的 params 中接收参数 -->
{{ this.$route.params.id }}
</div>
// 如果想要在组件刚开始加载时获取 id,并且根据 id 做一些数据操作,那就在对应的钩子函数中,获取路由参数
created() { // detail 组件生命周期的 created 钩子函数
const id = this.$route.params.id;
// code
}
用 created 和 mounted 函数,只能在第一个商品被渲染时响应,detail 组件在第一次被渲染之后,虽然路由变了,但是 created 和 mounted 不会重新执行。这种情况下,可以用 updated 来动态获取路由参数。也可以用 watch 来监听路由的变化。
watch: {
// to 和 from 分别表示路由切换前后的路由元信息
'$route'(to, from) {
// 对路由变化作出响应...
}
}
2. router-link 的 to属性传参
如果使用 <router-link> 标签的 to 属性动态传参,那么路由配置时不需要在 path 路径中预留参数的位置,直接传参并接收就可以了。
// router>index.js 的routes
routes: [
{
// 路径中不需要预留参数的位置
path: '/good-detail',
component: Detail
}
]
传参:
<!--
to 动态传参时,要传一个对象,要绑定 v-bind 指令
路由中的参数有两个列表,分别是 query 和 params
-->
<router-link
:to="{
path: '/good-detail',
query: {
id: 1
}
}"
>商品3</router-link>
接收参数:
// detail 组件的 created 钩子函数
created() {
const id = this.$route.query.id;
// code
}
这样传参,有个好处,就是有多个参数时,无论是配置还是传参,代码都非常简洁,如果有多个参数,直接列在 query 对象中就可以了。
但是也有个缺点,就是传递的参数会暴露在 url 中,如果参数中的信息是需要保护的信息,那么直接暴露就没有任何安全性了。
这就要用到 params,params 和 query 的区别就是 params 中的参数不会暴露在 url 中,query 会。
但是 params 需要和路由的 name 结合使用。
// router>index.js 的routes
routes: [
{
path: '/good-detail',
name: 'good-detail',
component: Detail
}
]
<router-link
:to="{
name: 'good-detail',
params: {
id: 1
}
}"
>商品3</router-link>
获取 params 中的参数:
// detail 组件的 created 钩子函数
created() {
const id = this.$route.params.id;
// code
}
注:
path 只能和 query 结合使用,name 可以和 query 或者 params 结合使用,但是 name 和 query 结合使用时,参数依旧会暴露。
3. push 时传参
// path 和 query 结合使用
this.$router.push({
path: '/good-detail',
query: {
id: 1
}
});
// name 和 query 结合使用
this.$router.push({
name: 'good-detail',
query: {
id: 1
}
});
// name 和 params 结合使用
this.$router.push({
path: '/good-detail',
params: {
id: 1
}
});
接受参数方式不变。
二、导航守卫和路由元信息
1. 导航守卫
通俗点说,导航守卫指在路由切换时,对组件中的数据或者用户信息做一些保护和判断。
比如用户从 A 组件切换到 B 组件,但是 B 组件中的内容是要根据用户的权限渲染的,不同权限的用户渲染不同的内容。就需要在切换之前拿到用户的权限信息,做判断之后再切换组件。
还有一种可能性,某个后台管理系统只能在用户登录之后才展示相对应的页面,但是用户可能已经知道了首页的路径,用户可能没经过登录直接在浏览器输入首页路径,要强行进入首页,那么在此之前,我们要做导航守卫。
其实我们可以把导航守卫理解成路由过程中的钩子函数。
全局守卫
// router>index.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
const router = new Router({
routes: [
// ...
]
});
// 全局前置守卫
router.beforeEach((to, from, next) => {
// code
});
// 全局后置钩子
router.afterEach((to, from) => {
// ...
});
export default router
全局的守卫会在每个路由发生变化时响应,但是有时候我们只需要在某个路由发生变化时做一些操作,并不需要所有路由全部响应切换。全局守卫的循环还是稍微有点耗性能。
某个路由自己的守卫
import Vue from 'vue'
import Router from 'vue-router'
import GoodDetail from '@/components/GoodDetail'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/good-detail',
component: GoodDetail,
beforeEnter: (to, from, next) => {
// 只有当前路由切换时要响应的代码
// 和其他路由没有任何关系
}
}
]
})
如果需要在某个组件中,捕获到路由变化之后或者之前,对数据做一些保留或清除动作。
比如从商品列表切换到商品详情,我们可以在详情组件路由切换成功的钩子函数中,获取路由参数,就可以使用组件中的路由守卫(当然也可以用组件生命周期钩子函数,也可以使用watch,这里组件中的路由守卫只是提供另一种可能性)。
组件内的守卫
// 某个组件的 export
export default {
name: 'Detail',
// vue-router 文档提供的示例
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
注:
beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
完整的导航流程解析
官网给了导航切换的整个细致流程及每个阶段的钩子函数。
- 导航被触发。
- 在失活的组件里调用离开守卫。
- 调用全局的 beforeEach 守卫。
- 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
- 在路由配置里调用 beforeEnter。
- 解析异步路由组件。
- 在被激活的组件里调用 beforeRouteEnter。
- 调用全局的 beforeResolve 守卫 (2.5+)。
- 导航被确认。
- 调用全局的 afterEach 钩子。
- 触发 DOM 更新。
- 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。
to, from, next
在上面的很多例子中,我们都能看到 钩子函数接收的参数,to,from,next。它们都代表特殊的意义和作用。
-
to: Route: 即将要进入的目标 路由对象
-
from: Route: 当前导航正要离开的路由
-
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
-
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
-
next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
-
next(’/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: ‘home’ 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。
-
next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
-
2. 路由元信息
在配置路由时,路由对应的某些固定数据,我们可以直接绑定在路由配置对象的 meta 对象中,然后在需要时获取。
// router>index.js 的 routes
routes: [
{
path: '/good-detail',
component: GoodDetail,
// 定义路由的时候可以配置 meta 字段:
meta: {
title: '商品详情',
ifSee: true
}
}
]
获取路由元信息:
// Detail 组件的 created
created() {
console.log(this.$route.meta);
}
History 模式
我们在运行项目时,能看到 url 中带有一个 # ,这个是 vue-router 默认的 hash 模式。因为正常情况下,切换浏览器的 url 浏览器中的内容是要刷新的,但是我们希望的是通过在 url 中切换路由来实现页面组件的切换,所以 vue-router 在 url 中添加了 # 号,这样在切换路由导致 url 改变时不会刷新页面。其实 <router-link> 标签最终渲染的真实 DOM 是 <a>,to 属性是 <a> 标签的 href,# 是锚点:
<a data-v-957c9522="" href="#/good-detail" class="router-link-exact-active router-link-active">详情</a>
如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。
const router = new VueRouter({
mode: 'history',
routes: [...]
})
当使用 history 模式时,URL 就像正常的 url,例如 http://yoursite.com/user/id。
只是设置成 history 之后,一些与后台的数据交互需要依赖后台配置。
扫码拉你进入前端技术交流群

本文详细介绍了Vue中路由参数的传递,包括query和params的区别,如何在组件中获取参数。同时讲解了导航守卫的使用,如beforeRouteEnter等,以及路由元信息的设置和获取。最后讨论了History模式,解释了其在不使用#的情况下实现页面跳转的原理,并提到了后台配置的需求。
1908

被折叠的 条评论
为什么被折叠?



