felix-cao / Blog

A little progress a day makes you a big success!
31 stars 4 forks source link

Vue 路由管理器(Vue Router)的路由嵌套 #157

Open felix-cao opened 5 years ago

felix-cao commented 5 years ago

在实际的开发中,一个应用程序通常由多层嵌套的组件组合而成。同样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件。本文就主要聊一聊这种路由嵌套

一、组件的嵌套

Vue 对组件的定义是可复用的 Vue 实例,且带有一个名字,Vue 官方 的文档并没有明确的示例来说明组件的嵌套,只是用下面一张图来说明组件嵌套形成的一个巨大的组件树,

image

实际上,组件嵌套形成的组件树与使用 HTML 标签嵌套形成的 DOM 树一样,是很简单很基础的,因此,官方文档并没有过多的笔墨来阐述组件嵌套知识点。

<parent>
  <my-component>
    <son1></son1>
    <son2></son2>
  </my-component>

  <my-brother></my-brother>
</parent>

上面的代码 parent, myComponent, son1, son2,都是自定义组件,这种嵌套关系从而形成了组件树,关于组件的其他知识请阅读 组件基础组件注册

二、路由嵌套中的 router-view

路由嵌套主要是通过 vue-router 中提供的 router-view 组件及其路由配置中的 children 属性的组合使用而实现的。

2.1、场景描述

假设我们有下面的场景,在路由 /user/:id 下嵌套 profilescores,路径,这种路由对应的组件关系如下:

/user/foo/profile                     /user/foo/scores
+------------------+                  +-----------------+
| User             |                  | User            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Scores       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

2.2、router-view

router-viewvue-router 给我们提供的一个 functional 组件,主要功能是将路由配置中的 component 属性对应的组件渲染到 router-view 这个位置,我大部分情况下都把 router-view 理解成一个占位符。

2.2.1、单个组件对应一个 router-view

下面代码位于 index.html 入口,在 html 中使用 router-view 组件

<div id="app">
  <router-view></router-view>
</div>

在路由配置中,配置 component 属性

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User }
  ]
})

我用图示来画一下这种对应关系:

image

2.2.2、多个组件对应的 router-view

我们也顺便说一说多个组件对应的 router-view,主要是利用了 router-view 组件中的 name 属性,其默认值为 default,而多个 router-view 利用 name 属性对应的路由配置 components 对象,

html 中配置两个 <router-view>

<div id="app">
  <router-view></router-view> <!--name 默认值为 default-->
  <router-view name="left"></router-view>
</div>

在路由中配置 components

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}

const Nav = {
  template: '<div>Nav</div>'
}

const router = new VueRouter({
  routes: [
    { path: '/user/:id', components: { left: Nav, default: User } }
  ]
})

图解一下这种对应关系:

image

我们通常把 components 里配置的对象叫做 命名视图

2.3、组合 transition 和 keep-alive

Vue 给我们提供了 transitionkeep-alive 两个非常有用的组件,有时候,我们将他们与 <router-view> 组合使用形成一些动画效果。

三、路由嵌套中的 children 属性配置

下面接着 2.2.1 中的代码来实现 2.1 的应用场景。

现在我们在 User 组件的模板添加一个 <router-view>

const User = {
  template: `
    <div class="user">
      <h2>User {{ $route.params.id }}</h2>
      <router-view></router-view>
    </div>
  `
}
const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User,
      children: [
        {
          // 当 /user/:id/profile 匹配成功,
          // UserProfile 会被渲染在 User 的 <router-view> 中
          path: 'profile',
          component: UserProfile
        },
        {
          // 当 /user/:id/posts 匹配成功
          // UserPosts 会被渲染在 User 的 <router-view> 中
          path: 'posts',
          component: UserPosts
        }
      ]
    }
  ]
})

那么,此时,我们在入口 index.html 中,放的 <router-view> 是最顶层的出口, 而这里 User 组件的 <router-view> 是用来渲染上面路由配置 children 属性中配置的 router

要注意,以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。