动态路由
一、动态路由匹配
1.1、路由传参
- 配置路由
在router/index.js下
const router = new VueRouter({
routes: [
// 动态路径参数 以冒号开头,相当于在path里声明了一个变量 id
{ path: '/user/:id', component: User }
]
})
- 跳转
在要跳转的组件下
//匹配上 '/user/:id' 路径,01001的值会赋给id
<router-link to="/user/01001">用户01001的信息</router-link>
- 获取传来的值(此处为id的值)
在跳转到的组件中
//模板里的写法:
$route.params.id
//script里的写法:
this.$route.params.id
注意:(此处是$route,不是$router)
$router:
表示vueRouter对象,由于我们在vue对象里把vueRouter对象植入到根属性里,所以,在组件内部是可以使用$router拿到该对象的。
$route:
表示匹配到的当前路由对象,简单理解为,路由配置中的某个json对象。
1.2、捕获所有路由或 404 路由
- 使用通配符 *
如:
'*' //会匹配所有路径
'/user-*' 会匹配以 `/user-` //开头的任意路径
注意:路由匹配的顺序是按照路由配置的顺序进行的,所以,不能把 * 的路径放在最前面,否则,后面的路由配置都不起作用了。
- 当使用一个通配符时,
$route.params
内会自动添加一个名为pathMatch
参数。它包含了 URL
通过通配符被匹配的部分。
如:
路由跳转
this.$router.push('/user-admin')
组件里:(可以通过pathMatch拿到*代表的值)
this.$route.params.pathMatch // 'admin'
- 404
在路由配置最后加一个not found配置,找不到则跳到该页面
{
path: '*',
component: 404组件
}
二、命名路由
给路由起个名字,这样就可以用名字来指定路由
- 配置路由
const router = new VueRouter({
routes: [
{
path: '/user/:userId',
name: 'user',
component: User
}
]
})
- 跳转
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
三、重定向
在router/index.js文件中(使用redirect)
{
path: '/', //默认页
redirect: '/index' //会重定向到/index配置中
},
{
path:'/index',
component:index,
},
四、路由传参(query)
query是路由传参的另一种方式,我们来看看和params有什么不同吧
- 路由配置不用改(不用动态路由匹配)
在index.js文件中
{ path: '/user', component: User }
- 跳转时,使用 path
//跳转时,使用字符串
//声明式:
<router-link to="/Reg?userid=007&username=mjl">User</router-link>
//编程式:
this.$router.push("/Reg?userid=007&username=mjl");
//跳转时,使用对象:
//声明式:
<router-link :to="{ path: '/user', query: { id: '01001' }}">User</router-link>
//编程式:
$router.push({ path: '/user', query: { id: '01001' }})
注意:如果提供了 path,那么params 会被忽略
// 带查询参数,变成 /user?id=01001
- 接收参数
//模板里的写法:
$route.query.参数名
//script里的写法:
this.$route.query.参数名
此处依然是$route
query:传递多个参数时,使用query方式,地址栏方便阅读
params:传递一个参数时,使用params
五、路由传参和props
首先,我们要知道:
一个组件在项目中,有两种使用方式(组件显示在浏览器上):
1、自定义标签的方式,
外部给组件传数据,用props
2、使用路由跳转的方式,
外部给组件传数据,用params或者query。
当一个组件需要从外部传入数据, 并且在项目中,这两种方式的使用都会出现,那么,在组件内部就需要适应这两种情况。
那如何使用 props
属性将组件和路由解耦:
很简单,在index.js文件中配置路由
{ path: '/user/:id', component: User, props: true },
props
被设置为 true
,route.params
将会被设置为组件属性。
-
如
此时已经配置了props为true,那么不论是路由传参还是props传参,都从组件的props里拿到数据
const User = {
props: ['id'],
template: '<div>User {{ id }}</div>'
}
console.log(this.props[0])//拿传来的数据
六、嵌套路由
有时候,我们只需要局部组件的跳转,这就需要用到路由嵌套
- 路由配置
在index.js文件中
const router = new VueRouter({
routes: [
{
path: '/user/:id',
component: User,
children: [
{
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 <router-view> 中
path: 'profile',
component: UserProfile //子组件UserProfile显示在父组件User里的<router-view>
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 <router-view> 中
path: 'posts',
component: UserPosts//子组件UserPosts显示在父组件User里的<router-view>
}
]
}
]
})
-
组件的展示:
子组件会展示在父组件里的
<router-view>
的位置。
七、路由模式
路由模式分为两种:hash和history。
-
history配置
只需要加mode即可
let router = new VueRouter({ //插件路由对象
routes,
// mode:'hash'//哈希模式 location.href
mode:'history'//历史记录 history.pushState
});
-
区别:
1)、外观上
hash模式时,路径上有#。
history模式时,路径上没有#。
2)、跟后端有关的区别
hash模式不会给后端发请求
history模式会给后端发请求,需要后端配合。要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个
index.html
页面,这个页面就是你 app 依赖的页面。否则,就会返回404。如果后端有同名的url,那么就会找后端的url。
八、路由守卫
8.1、全局守卫
全局守卫包括全局前置路由守卫和全局后置路由守卫
-
过程:
1、请求一个路径:如:/Index
2、经历前置守卫(路由配置前)
决定了能去哪个路径
3、根据去的路径,找对应component(路由配置)
4、经过后置守卫(路由配置后)
5、创建组件
// src/router/index.js
//前置钩子
router.beforeEach((to, from, next) => {
// to: 目标路由
// from: 当前路由
// next() 跳转 一定要调用
next(false);//不让走
next(true);//继续前行
next('/login')//走哪
next({path:'/detail/2',params:{},query:{}})//带点货
// 守卫业务
if(to.path=='/login' || to.path=='/reg' ){
next(true)
}else{
//是否登录的判断
if(没有登录过){
next('/login');
}else{
next(true);
}
}
})
//后置
router.afterEach((to,from)=>{
//全局后置守卫业务
})
8.2、路由独享守卫(只有前置)
// src/router/index.js
{
path: '/user',
component: User,
//路由独享守卫
beforeEnter: (to,from,next)=>{ //路由独享守卫 前置
console.log('路由独享守卫');
if(Math.random()<.5){
next()
}else{
next('/login')
}
}
}
8.3、组件内部守卫
//在组件内部写:
//组件内部钩子
beforeRouteEnter (to, from, next) {//前置
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {//后置
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
注意:
路由独享守卫,守的是path
组件内部守卫,守的是component
九、路由元信息
定义路由的时候配置 meta
字段
- 配置
meta
//src/plugins/router.js
{
path: '/home',
component: Home,
meta: { requiresAuth: true }
}
- 访问
meta
字段
this.$route.meta
to.meta
十、路由懒加载
当打包构建应用时,JavaScript 包会变得非常大,影响页面(特别是首次)加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。