Vue 组件之间通过路由传参

在组件中可以通过路由进行跳转,在跳转的同时可以传递一些参数

更多精彩

官方提供的解决方案

  1. 路由组件传参 - Vue Router
  2. 上述链接就是官方对于路由组件传参的解决方案,分别为
    • 布尔模式
    • 对象模式
    • 函数模式

简单易懂的布尔模式

  1. 就是在指定路由的配置中添加 props: true ,那么子组件就可以识别父组件在链接中携带的参数
  2. 例如在 router.js 中指定如下配置
1
2
3
4
5
6
7
const router = new VuewRouter({
  routes: [
    path: '/knowledge/:id',
    component: resolve => require(['views/knowledge/form'], resolve),
    props: true
  ]
})
  1. 同时在子组件中添加
1
2
3
4
5
6
props: {
  id: {
    type: String,
    default: '0'
  }
}
  1. 那么当父组件通过 /knowledge/1 跳转到子组件时,在子组件中执行 console.log(this.id) ,输出结果就会是 1
  2. 如果 router.js 中对应路由没有添加 props: true ,在子组件中执行的结果则是 0

易于扩展的函数模式

  1. 相对于简单易懂的布尔模式,函数模式的优势则是易于扩展
  2. 假设存在一个场景:父组件在向子组件跳转时,可能传参,也可能不传参,这个时候应该如果定义路由格式

布尔模式的局限性

  1. 如果用布尔模式,由于参数是被拼接在组件之间的请求链接上,所以就算父组件向子组件跳转时不需要传参,为了保证能跳转成功,也必须传递一个默认值,否则路由将无法正确识别到指定的子组件
  2. 例如父子组件之间跳转的请求链接是 /knowledge/:id ,那么父组件在向子组件跳转时,不论有没有对应的 id 需要传递,都必须在跳转链接上携带一个值,以确保链接能被正确识别
  3. 如果将 0 作为一个无意义的值,则是在需要传参时使用 /knowledge/1 ,在不需要传参时使用 /knowledge/0

函数模式的优势

  1. 如果使用函数模式,则可以有效避免上述情况,在 router.js 中指定如下配置
1
2
3
4
5
6
7
8
9
const router = new VuewRouter({
  routes: [
    path: '/knowledge',
    component: resolve => require(['views/knowledge/form'], resolve),
    props: (route) => ({
      id = route.query.id
    })
  ]
})
  1. 子组件中依旧添加
    1
    2
    3
    4
    5
    6
    props: {
      id: {
     type: String,
     default: '0'
      }
    }
    
  2. 那么当父组件要跳转到子组件,同时需要携带参数时,通过 /knowledge?id=1 即可
  3. 当父组件要跳转到子组件,却不需要传递参数时,通过 /knowledge 即可

函数模式容易被误会的劣势

  1. 你可能会想到,那么如果有多个参数需要传递
  2. 使用布尔模式只需要 /knowledge/:id/:pid/:sid 即可,同时在子组件指定对应的 props 即可完成接收
  3. 使用函数模式则不仅要在子组件完成相同的操作,还需要在 router.js 中指定如下配置
1
2
3
4
5
6
7
8
9
10
11
const router = new VuewRouter({
  routes: [
    path: '/knowledge',
    component: resolve => require(['views/knowledge/form'], resolve),
    props: (route) => ({
      id = route.query.id,
      pid = route.query.pid,
      sid = route.query.sid
    })
  ]
})
  1. 其实不然,如果有多个参数,利用 ES6 的特性,函数模式传参可以简写为如下格式
    • 只需要按照如下格式编写,就会自动将 route.query 中所有的参数都解耦为上述格式
1
2
3
4
5
6
7
const router = new VuewRouter({
  routes: [
    path: '/knowledge',
    component: resolve => require(['views/knowledge/form'], resolve),
    props: (route) => route.query
  ]
})

布尔模式和函数模式的混用

  1. 布尔模式和函数模式其实都很好,小孩子才做选择,成年人自然是两个都想要,那么怎么做呢?
  2. 如果在 router.js 中指定如下配置
1
2
3
4
5
6
7
8
9
const router = new VuewRouter({
  routes: [
    path: '/knowledge/:id',
    component: resolve => require(['views/knowledge/form'], resolve),
    props: (route) => ({
      pid = route.query.pid
    })
  ]
})
  1. 那么在父组件中通过 /knowledge/1?pid=2 跳转到子组件,是否可以同时拿到 idpid 呢?
  2. 答案是不行,只能顺利拿到 pid ,因为启用布尔模式的前提是 props: true ,而这里的 props 已经被用来接收函数了
  3. 成年人显然不高兴了,必须想办法两个都拿到,其实只要将配置改为如下格式即可
1
2
3
4
5
6
7
8
9
10
const router = new VuewRouter({
  routes: [
    path: '/knowledge/:id',
    component: resolve => require(['views/knowledge/form'], resolve),
    props: (route) => ({
      id = route.params.id,
      pid = route.query.pid
    })
  ]
})
  1. 只需要这样,通过 /knowledge/1?pid=2 就可以同时拿到 id=1 以及 pid=2

混用模式的精简版

  1. 都已经做到这一步了,可能那些有代码洁癖的家伙还是会不高兴
  2. 因为如果有多个链接参数,和多个可选参数,例如以下配置,岂不是显得更加繁琐
1
2
3
4
5
6
7
8
9
10
11
12
const router = new VuewRouter({
  routes: [
    path: '/knowledge/:id/:sid',
    component: resolve => require(['views/knowledge/form'], resolve),
    props: (route) => ({
      id = route.params.id,
      sid = route.params.sid,
      pid = route.query.pid,
      mid = route.query.mid
    })
  ]
})
  1. 对于上述窘境,我们可以简单分析一下,路由组件的传参的函数模式,其实就是表示 props 可以接收一个函数
  2. 而函数中其实使用的是一个被封装后的对象,所以我们才能将函数模式精简为 props: (route) => route.query
  3. 那么 route.paramsroute.query 其实就是两个对象,只要将这两个对象合并成一个对象不就可以了吗?
  4. 这个时候就需要使用 Lodash 的 Merge 函数,进行如下修改
1
2
3
4
5
6
7
const router = new VuewRouter({
  routes: [
    path: '/knowledge/:id/:sid',
    component: resolve => require(['views/knowledge/form'], resolve),
    props: (route) => _.merge(route.params, route.query)
  ]
})