[vue] vue-router(二)_嵌套路由和编程式导航

304 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 17 天,点击查看活动详情

嵌套路由

实际生活中的应用界面,通常由多层嵌套的组件组合而。同样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件

比如一个后台管理系统,每个页面都有相同的头部和左侧菜单,点击左侧不同菜单时,切换显示内容

image.png

如何实现嵌套路由?

  • 1、<router-view>

    <router-view>的位置就是匹配组件渲染显示的位置;最顶层出口<router-view>渲染整个页面,在一个被渲染的组件中可以包含嵌套<router-view>实现局部切换内容渲染组件

        <template>
          <div class="about">
            <h1>This is an about page</h1>
            <!--this.$route.path = '/about/detail1'-->
            <router-link to="detail1">detailOne</router-link> |
            <!--this.$route.path = '/detail1'-->
            <router-link to="/detail1">detailOne</router-link> |
            <!--this.$route.path = '/about/detail2'-->
            <router-link to="/about/detail2" >detailTwo</router-link>
            
            <br>
            <!--路由的路径地址太长可以直接使用name-->
            <router-link :to="{name: 'detailOne'}">detailOne</router-link> |
            <router-link :to="{name: 'detailTwo'}">detailTwo</router-link>
            <router-view></router-view>
          </div>
        </template>
    
  • 2、路由参数配置

要在嵌套的出口(<router-view>)中渲染组件,通过children参数配置


{
    path: '/about',
    name: 'about',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue'),
    children: [
      {
        // 相对于外层路由
        path: 'detail1',
        name: 'detailOnee',
        component: () => import('../views/details/detailOne.vue'),
      },
      // 以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。
      {
        path: '/detail1',
        name: 'detailOne',
        component: () => import('../views/details/detailOne.vue'),
      },
      {
        path: '/about/detail2',
        name: 'detailTwo',
        component: () => import('../views/details/detailTwo.vue'),
      }
    ]
}
// 动态路由嵌套
// <router-link :to="{name: 'detailOnee',params: {id: '123'}}">detailOne</router-link> 
// 匹配path: /about/123/detail1
{
    path: '/about/:id',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue'),
    children: [
      {
        // 相对于外层路由, 要匹配/about/:id/detail1
        path: 'detail1',
        name: 'detailOnee',
        component: () => import('../views/details/detailOne.vue'),
      },
      // 以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。
      {
        path: '/detail1',
        name: 'detailOne',
        component: () => import('../views/details/detailOne.vue'),
      },
      {
        path: '/about/detail2',
        name: 'detailTwo',
        component: () => import('../views/details/detailTwo.vue'),
      }
    ]
}

以 / 开头的嵌套路径会被当作根路径。 不受嵌套路由路径限制。 如上面代码中

  1. path: 'detail1', 必须匹配/about/:id/detail1
<!--/about/123/detail1-->
<router-link :to="{name: 'detailOnee',params: {id: '123'}}">detailOne</router-link> 
  1. /detail1/about/detail2, 就无须设置嵌套的路径,直接
<!--/detail1-->
<router-link to="/detail1">detailOne</router-link>
<!--/about/detail2-->
<router-link to="/about/detail2" >detailTwo</router-link>

编程导航

声明式编程式
<router-link :to="...">router.push(...)

使用js代码实现页面跳转

  • 路由导航:router.push(location, onComplete?, onAbort?)

    1. location:要去的目的地
    2. onComplete:导航成功完成的回调
    3. onAbort:导航终止时的回调

    后面两个回调一般很少用到。

  • 使用location的传参方式

    // 字符串
    router.push('home')
    
    // 对象
    router.push({ path: 'home' })
    
    // 命名的路由
    router.push({ name: 'user', params: { userId: '123' }})
    
    // 带查询参数,变成 /register?plan=private
    router.push({ path: 'register', query: { plan: 'private' }})
    
    // 使用path 时,params会被忽略,
    const userId = '123'
    router.push({ name: 'user', params: { userId }}) // -> /user/123
    router.push({ path: `/user/${userId}` }) // -> /user/123
    // 这里的 params 不生效
    router.push({ path: '/user', params: { userId }}) // -> /user
    

同样的规则也适用于 router-link 组件的 to 属性。

总结router.push常用传参方式:

  1. 直接传递path值(字符串)
  2. 传递对象时,直接传递{path: 使用模板字符串拼接路由地址与参数}
  3. path + query => '/path?query=data', 同get请求拼接参数一样
  4. name + params => '/name/params', 注意在路由配置中配置对应动态路径参数,否则刷页面会造成参数丢失问题。动态路由配置传送门

注意事项-组件复用

使用动态路由时,路由只有参数发生变化时,不同参数的路由渲染的都是同一个组件,组件会被复用,这样组件的生命周期钩子也不会再被调用。

那么假如需要根据路由参数获取数据的话,如何能监听到参数变化?
使用watch监听路由变化

watch: {
    $route: {
        handler(n,o){
            console.log(n)
        },
        immediate: true
    }
}