Skip to content
On this page
ads via Carbon Design and Development tips in your inbox. Every weekday. ads via Carbon

Rotas Encaixadas

Algumas UIs da aplicação são compostas de componentes que são encaixados vários níveis de profundidade. Neste caso, é muito comum que os segmentos de uma URL corresponda à uma certa estrutura de componentes encaixados, por exemplo:

/user/johnny/profile                     /user/johnny/posts
+------------------+                  +-----------------+
| User             |                  | User            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Posts       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+
/user/johnny/profile                     /user/johnny/posts
+------------------+                  +-----------------+
| User             |                  | User            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Posts       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

Com a Vue Router, podes expressar este relacionamento usando as configurações de rota encaixada.

Dada a aplicação que criamos no último capítulo:

html
<div id="app">
  <router-view></router-view>
</div>
<div id="app">
  <router-view></router-view>
</div>
js
const User = {
  template: '<div>User {{ $route.params.id }}</div>',
}

// estas rotas são passadas para o `createRouter`
const routes = [{ path: '/user/:id', component: User }]
const User = {
  template: '<div>User {{ $route.params.id }}</div>',
}

// estas rotas são passadas para o `createRouter`
const routes = [{ path: '/user/:id', component: User }]

O <router-view> aqui é um router-view de alto nível. Ele apresenta o componente correspondido por uma rota de alto nível. Similarmente, o componente apresentado também pode conter o seu próprio, <router-view> encaixado. Por exemplo, se adicionarmos um dentro do modelo de marcação do componente User:

js
const User = {
  template: `
    <div class="user">
      <h2>User {{ $route.params.id }}</h2>
      <router-view></router-view>
    </div>
  `,
}
const User = {
  template: `
    <div class="user">
      <h2>User {{ $route.params.id }}</h2>
      <router-view></router-view>
    </div>
  `,
}

Para apresentar os componentes dentro deste router-view encaixado, precisamos usar a opção children em quaisquer das rotas:

js
const routes = [
  {
    path: '/user/:id',
    component: User,
    children: [
      {
        /*
          UserProfile será apresentado dentro do <router-view> do User
          quando `/user/:id/profile` for correspondido
        */
        path: 'profile',
        component: UserProfile,
      },
      {
        /*
          UserPosts será apresentado dentro do <router-view> do User
          quando `/user/:id/posts` for correspondido
        */
        path: 'posts',
        component: UserPosts,
      },
    ],
  },
]
const routes = [
  {
    path: '/user/:id',
    component: User,
    children: [
      {
        /*
          UserProfile será apresentado dentro do <router-view> do User
          quando `/user/:id/profile` for correspondido
        */
        path: 'profile',
        component: UserProfile,
      },
      {
        /*
          UserPosts será apresentado dentro do <router-view> do User
          quando `/user/:id/posts` for correspondido
        */
        path: 'posts',
        component: UserPosts,
      },
    ],
  },
]

Nota que caminhos encaixados que começam com / serão tratados como um caminho de raiz. Isto permite-te influenciar o encaixamento do componente sem ter de usar uma URL encaixada.

Conforme podes ver a opção children é apenas um outro arranjo de rotas como o próprio routes. Portanto, podes continuar a encaixar as visões tanto quanto precisares.

Até este ponto, com a configuração acima, quando visitas /user/eduardo, nada será apresentado dentro da router-view do User, porque nenhuma rota encaixada é correspondida. Talvez queiras apresentar alguma coisa lá. Em tal caso podes fornecer um caminho encaixado vazio:

js
const routes = [
  {
    path: '/user/:id',
    component: User,
    children: [
      /*
        UserHome será apresentado dentro da `<router-view>` do User
        quando `/user/:id` for correspondido
      */
      { path: '', component: UserHome },

      // ...outras sub-rotas
    ],
  },
]
const routes = [
  {
    path: '/user/:id',
    component: User,
    children: [
      /*
        UserHome será apresentado dentro da `<router-view>` do User
        quando `/user/:id` for correspondido
      */
      { path: '', component: UserHome },

      // ...outras sub-rotas
    ],
  },
]

Uma demonstração em funcionamento deste exemplo pode ser encontrada nesta ligação.

Rotas Encaixadas Nomeadas

Quando estamos a lidar com Rotas Nomeadas, normalmente nomeias as rotas filhas:

js
const routes = [
  {
    path: '/user/:id',
    component: User,
    // repara em como apenas a rota filha tem um nome
    children: [{ path: '', name: 'user', component: UserHome }],
  },
]
const routes = [
  {
    path: '/user/:id',
    component: User,
    // repara em como apenas a rota filha tem um nome
    children: [{ path: '', name: 'user', component: UserHome }],
  },
]

Isto garantira que a navegação para /user/:id sempre exibirá a rota encaixada.

Em alguns cenários, podes querer navegar para uma rota nomeada sem navegar para a rota encaixada. Por exemplo, se quiseres navegar para /user/:id sem exibir a rota encaixada. Neste caso, também podes nomear a rota pai mas nota que ao recarregar a página sempre exibirá a filha encaixada já que é considerada uma navegação para o caminho /users/:id ao invés da rota nomeada:

js
const routes = [
  {
    path: '/user/:id',
    name: 'user-parent'
    component: User,
    children: [{ path: '', name: 'user', component: UserHome }],
  },
]
const routes = [
  {
    path: '/user/:id',
    name: 'user-parent'
    component: User,
    children: [{ path: '', name: 'user', component: UserHome }],
  },
]

Lançado sob a licença MIT.