Vue-router基础知识
1. 响应路由参数的变化
定义一个路由如下:
12345678910111213141516 | 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 对象:
123456789 | export default { watch: { ‘$route‘ (to, from) { console.log("from:"+from.path); console.log("to:"+to.path); // 对路由变化作出响应... } }} |
注意:上面这段代码只有在$route变化时才会执行。
2. 捕获所有路由或 404 Not found 路由
常规参数只会匹配被 / 分隔的 URL 片段中的字符。如果想匹配任意路径,我们可以使用通配符 (*):
12345 | { 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。
以下是一些实例:
12345678910111213 | //home为定义的路由名称// 字符串router.push(‘home‘)// 对象router.push({ path: ‘home‘ })// 命名的路由,userId为路由参数router.push({ name: ‘user‘, params: { userId: ‘123‘ }})// 带查询参数,变成 /register?plan=privaterouter.push({ path: ‘register‘, query: { plan: ‘private‘ }})const userId = ‘123‘router.push({ name: ‘user‘, params: { userId }}) // -> /user/123router.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的路由定义中使用了同级视图:
12345678910111213141516171819202122232425262728 | { 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 将组件和路由解耦:
1234567891011121314151617181920212223242526272829303132333435 | { 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 将会被设置为组件属性。
1234567 | { path:‘project/:projectId‘, name:‘project‘, //布尔模式 props:true, component: Project} |
123456789 | { path:‘project2/:projectId‘, name:‘project2‘, components: { default: () => import(‘@/components/ProjectDetailHead.vue‘), detail: () => import(‘@/components/ProjectDetailContent.vue‘) }, props:{default:false,detail:true}} |
- 对象模式
如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用。
1234567 | { path:‘projectlist‘, name:‘projectlist‘, component: () => import(‘@/views/ProjectList.vue‘), //对象模式 props: { listTitle: "项目列表展示" }} |
- 函数模式
你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合等等。
1234567 | { 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