본문 바로가기

Vue.js

[Udemy Vue 완벽가이드 Section13] 182. 이름이 있는(named) router-view로 여러 라우트 렌더링

 

 

쿼리 매개변수가 있는 이러한 객체를 to 프로퍼티의 값으로 넣어 이동시키는 기능을 구현해보았다.

<!--TeamsItem.vue-->
<template>
  <li>
    <!--생략-->
    <router-link :to="teamMembersLink">View Members</router-link>
  </li>
</template>

<script>
  computed: {
    teamMembersLink() {
      return {
        name: 'team-members',
        params: { teamId: this.id },
        query: { sort: 'asc' },
      };
    },
  },
</script>

 

# 여러 개의 router-view

애플리케이션에서 유용하게 쓰일 또 다른 기능이 있다.

같은 레벨에 생성하는 여러 개의 router-view.

 

이미 데모 앱에서 여러 개의 router-view를 만들어보았다.

App.vue 파일과 TeamsList.vue 컴포넌트에 router-view가 하나씩 있다.

 

TeamList컴포넌트에 있는 <router-view>는 TeamsList 컴포넌트를 로드하는 route에 속한 중첩 라우트(children)를 위해 만들었다.

{
  name: 'teams',
  path: '/teams',
  component: TeamsList,
  meta: { needsAuth: true },
  children: [
    {
      name: 'team-members',
      path: ':teamId',
      component: TeamMembers,
      props: true,
    },
  ],
},

 

 

하지만 같은 레벨에도 여러 router-view를 생성할 수 있다.

 

예를 들어 App.vue 파일에 footer 요소를 만든다고 가정해보자. footer 요소에도 router-view 요소를 추가할 수 있다.

<!--App.vue-->
<template>
  <the-navigation></the-navigation>
  <main>
     <router-view></router-view>
  </main>
  <footer>
     <router-view></router-view>
  </footer>
</template>

물론 같은 레벨에서 같은 라우트를 다루는 router-view가 두 개 있는건 그다지 큰 도움이 되지 않는다.

이대로 저장하고 페이지를 새로고침하면 모든 페이지가 두번씩 로드되는걸 확인할 수 있다.

router-view가 두개이므로 당연한 결과.

 

대신, 같은 레벨에 여러 router-view를 생성하면 유용한 기능을 추가할 수 있게 된다.

한 라우트에 여러 컴포넌트를 로드할 수 있고, 그 여러 컴포넌트를 여러 router-view에 보낼 수 있다.

이를 위해 TeamsFooter.vue 파일을 만들어보자.

간단한 템플릿이 있는 파일로, 우리가 알아볼 수 있게 'Teams Footer'를 작성하자.

<!--TeamsFooter.vue-->
<template>
  <h2>Teams Footer</h2>
</template>

 

UsersFooter.vue 파일도 만들어보자.

<template>
  <h2>Users Footer</h2>
</template>

 

Teams 페이지인지 Users 페이지인지에 따라 footer로 로드할 두 개의 컴포넌트를 생성했다.

Vue 라우터를 이용하면 쉽게 구현할 수 있다.

라우트 구성에서 라우트 별로 둘 이상의 컴포넌트를 등록할 수 있다.

 

# 방법

/teams 라우트의 경우, component 대신 components(복수형)로 작성해보자..

components는 객체를 취한다. 이 객체에는 key-value 쌍을 정의한다.

key로 여러 router-view를 구분하고, 값으로는 해당 router-view에 로드해야하는 컴포넌트가 들어간다.

 

이름 없는 router-view를 가리키는 key로 'default'를 넣어보자.

그리고 해당 default에 TeamsList 컴포넌트를 설정한다.

여기에 key로 footer를 추가할 수 있다. 이름을 footer로 지정한 router-view를 가리킨다.

그리고 해당 router-view에서 렌더링할 컴포넌트를 설정하자. TeamsFooter 컴포넌트를 불러와서 TeamsFooter를 설정할 수 있다.

이제 footer의 값으로 TeamsFooter를 설정할 수 있다.

// main.js
import TeamsFooter from './components/teams/TeamsFooter.vue';
import UsersFooter from './components/users/UsersFooter.vue';

//..생략
  routes: [
    {
      name: 'teams',
      path: '/teams',
      components: { default: TeamsList, footer: TeamsFooter },
      //..생략
    },
  ],

 

슬롯에 이름을 부여할 수 있는 것처럼 router-view에 이름을 부여하면 그 역할을 수행한다.

<footer>에 작성한 <router-view>에 footer라는 이름을 부여하자. 이름은 원하는 대로 지으면 된다.

<template>
  <the-navigation></the-navigation>
  <main>
    <router-view></router-view>
  </main>
  <footer>
    <router-view name="footer"></router-view>
  </footer>
</template>

상단 main의 <router-view>에도 이름을 부여할 수 있지만, 슬롯과 마찬가지로 같은 레벨에서 router-view 하나는 이름이 없어도 괜찮다.

이름이 없으면 기본 router-view가 된다.

 

 

/users 라우트에도 동일하게 적용할 수 있다.

/users 라우트에는 component 대신 components를 사용하고 default키의 값으로 UsersList를 설정한다.

footer의 값으로는 UsersFooter를 설정한다.

// main.js
import TeamsFooter from './components/teams/TeamsFooter.vue';
import UsersFooter from './components/users/UsersFooter.vue';

//..생략
  routes: [
    {
      path: '/users',
      components: { default: UsersList, footer: UsersFooter },
      //..생략
    },
  ],

 

 

/users와 /teams 라우트에 기명 router-view를 적용했으니, catchAll 라우트인 /:notFound(.*) 라우트가 가진 한 개의 컴포넌트는 기본 라우트인 무기명 router-view에서 로드된다.

 

그러니 지원하는 router-view가 하나만 있다면(NotFound), /:notFound(.*) 라우트에 components를 설정할 필요가 없다.

 

코드를 이대로 저장하면 Team 목록과 footer인 'Teams Footer'를 볼 수 있다.

 

 

Users 페이지에선 당연히 아래에 'Users Footer'가 뜨고, 사용자 정보가 뜬다.

 

 

유효하지 않은 URL을 입력하면 NotFound 라우트가 뜬다.

유효하지 않은 URL은 기본 라우트인 기본 무기명 <router-view>로 이동하므로.

 

 

 

이렇게 기명 router-view는 더욱 복잡한 사용자 인터페이스를 구축하는데에 도움이 된다.

예를 들어 유연한 메인페이지 뿐만 아니라 유연한 footer도 만들 수 있다.

 

 

** 출처: 모든 내용은 Udemy Vue-완벽가이드 강의를 기반으로 작성하였습니다.