Vue-router基础知识

1. 响应路由参数的变化

定义一个路由如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/project/:projectId',
name: 'project',
component: () => import('./views/Project.vue')
}
]
})

在上面这段代码中以:号开头的(:projectId)是动态路由参数,当使用路由参数时,例如从 /project/1 导航到 /project/2,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。

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

1
2
3
4
5
6
7
8
9
export default {
watch: {
'$route' (to, from) {
console.log("from:"+from.path);
console.log("to:"+to.path);
// 对路由变化作出响应...
}
}
}

注意:上面这段代码只有在$route变化时才会执行。

2. 捕获所有路由或 404 Not found 路由

常规参数只会匹配被 / 分隔的 URL 片段中的字符。如果想匹配任意路径,我们可以使用通配符 (*):

1
2
3
4
5
{
path: '*',
name: 'page404',
component: () => import('./views/404.vue')
}

当使用通配符路由时,请确保路由的顺序是正确的,也就是说含有通配符的路由应该放在最后。路由 { path: ‘*’ } 通常用于客户端 404 错误。

以上两小节的相关代码实例gitHub地址:
https://github.com/johnnynie/vue-demos/tree/master/vue-router-demos/demo1

3. 使用js实现路由跳转(导航)

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

  • router.push(location, onComplete?, onAbort?)

在 Vue 组件实例内部,可以通过 $router 访问路由实例,因此在Vue组件实例内部,可以调用this.$router.push(location, onComplete?, onAbort?),下同。
这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

当你点击 时,这个方法会在内部调用,所以说,点击 等同于调用 router.push(…)。它将会导航到不同的URL。
以下是一些实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
//home为定义的路由名称
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由,userId为路由参数
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
  • router.replace(location, onComplete?, onAbort?)

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

  • router.go(n)

在 history 记录中向前或者后退多少步

4.使用嵌套视图与同级视图实现页面布局

为了实现一些复杂页面布局,我们经常需要用到嵌套视图,在定义路由时,通过children实现路由的嵌套关系。而在实现一些简单的页面时,如果不想为这个页面单独的创建一个.vue文件,我们也可以用同级视图,同级视图是指:一个界面中多个路由视图,可实现同级展示多个视图,而非嵌套。多个视图的情况下,需要给每个视图设置名字,如果 router-view 没有设置名字,那么默认为 default。
以下路由定义代码中实现了嵌套路由,其中在路由name为project的路由定义中使用了同级视图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
path: '/index',
name: 'layout',
component: () => import('@/views/Layout.vue'),
redirect: '/index/home',
children: [
{
path:'home',
name: 'home',
component: () => import('@/views/Home.vue')
},
{
path:'projectlist',
name:'projectlist',
component: () => import('@/views/ProjectList.vue'),
children:[
{
path:'project/:projectId',
name:'project',
components: {
default: () => import('@/views/ProjectDetailHead.vue'),
detail:() => import('@/views/ProjectDetailContent.vue')
}
}
]
}
]
}

详细的实例代码请访问以下GitHub地址:
https://github.com/johnnynie/vue-demos/tree/master/vue-router-demos/demo2

5.使用props实现路由组件传参

在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。
使用 props 将组件和路由解耦:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{
path:'projectlist',
name:'projectlist',
component: () => import('@/views/ProjectList.vue'),
//列表模式
props: { listTitle: "项目列表展示" },
children:[
{
path:'project/:projectId',
name:'project',
//布尔模式
props:true,
component: Project
}
]
},
// 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
{
path:'projectlist2',
name:'projectlist2',
component: () => import('@/views/ProjectList2.vue'),
//函数模式
props: (route) => ({ listTitle: route.query.title }),
children:[
{
path:'project2/:projectId',
name:'project2',
components: {
default: () => import('@/components/ProjectDetailHead.vue'),
detail: () => import('@/components/ProjectDetailContent.vue')
},
props:{default:false,detail:true}
}
]
}

这样你便可以在任何地方使用该组件,使得该组件更易于重用和测试。

props的书写有三种模式:布尔模式、对象模式、函数模式

  • 布尔模式

如果 props 被设置为 true,route.params 将会被设置为组件属性。

1
2
3
4
5
6
7
{
path:'project/:projectId',
name:'project',
//布尔模式
props:true,
component: Project
}
1
2
3
4
5
6
7
8
9
{
path:'project2/:projectId',
name:'project2',
components: {
default: () => import('@/components/ProjectDetailHead.vue'),
detail: () => import('@/components/ProjectDetailContent.vue')
},
props:{default:false,detail:true}
}
  • 对象模式

如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用。

1
2
3
4
5
6
7
{
path:'projectlist',
name:'projectlist',
component: () => import('@/views/ProjectList.vue'),
//对象模式
props: { listTitle: "项目列表展示" }
}
  • 函数模式

你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合等等。

1
2
3
4
5
6
7
{
path:'projectlist2',
name:'projectlist2',
component: () => import('@/views/ProjectList2.vue'),
//函数模式
props: (route) => ({ listTitle: route.query.title })
}

URL /projectlist2?title=项目列表展示 会将 {listTitle: ‘项目列表展示’} 作为属性传递给 projectlist2 组件。

详细的实例代码请访问以下GitHub地址:
https://github.com/johnnynie/vue-demos/tree/master/vue-router-demos/demo3

posted @ 2020-05-11 00:15  前端客  阅读(327)  评论(0编辑  收藏  举报