Vue3 - Not Found, 중첩된 라우트(Nested Routes)

Corner·2023년 1월 25일
0

Vue.js 실무

목록 보기
13/14

Not Found

라우터의 index.js

 {
   path: '/:pathMatch(.*)*',
   name: 'NotFound',
   component: NotFound
 }

views/NotFoundView.vue

<script setup></script>

<template>
    <div class="text-center py-5">
        <h1>Oops!</h1>
        <h2>404 Not Found</h2>
        <div class="text-muted">요청한 페이지를 찾을 수 없습니다!</div>
        <!--        {{ $route.params.pathMatch }} 슬래쉬로 구분하여 배열로 출력됨-->
        <div class="mt-4">
            <RouterLink to="/">
                <button class="btn btn-primary">HOME</button>
            </RouterLink>
        </div>
    </div>
</template>

<style scoped></style>

중첩된 라우트(Nested Routes)

실제 앱 UI는 일반적으로 여러 단계로 중첩 된 컴포넌트로 이루어져 있다. URL의 경로가 중첩된 컴포넌트의 특정 구조와 일치한다는 것

이게 무슨 말이냐면 특정 페이지로 들어갔을 때 일부 영역은 고정 시키고 특정 부분만 랜더링 해야하는 일이 발생할 수 있다.

이럴 때 원하는 영역에 <RouterView>를 선언하면 된다.

그러면 결과적으로 RouterView안에 또 RouterView가 있는 것, 중첩된 라우터 형태가 된다.

views/nested/NestedView.vue

<script setup></script>

<template>
    <ul class="nav nav-pills">
     <li class="nav-item">
            <a class="nav-link active" aria-current="page" href="one">Nested One</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" href="two">Nested Two</a>
        </li>
    </ul>
</template>

<style scoped></style>

페이지 컴포넌트를 만들고, 라우터 맵핑 후 TheHeader.vue에서 라우터 링크를 하나 연결해준다.

<li class="nav-item">
  <RouterLink class="nav-link" active-class="active" to="/nested">Nested</RouterLink>
</li>

/nested url로 넘어왔을 때 Vue 라우터 구성 컴포넌트를 보면 TheView안에 RouterView가 있기 때문에

목록 경로에 따라서 해당 페이지의 영역만 변경되어 렌더링 된다.

NestedView.vue안에 <RouterView>를 추가한다. a태그도 라우터링크 태그로 바꿔주자.

<script setup></script>

<template>
    <ul class="nav nav-pills">
        <li class="nav-item">
            <RouterLink to="one" class="nav-link" active-class="active"> Nested One</RouterLink>
        </li>
        <li class="nav-item">
            <RouterLink to="two" class="nav-link" active-class="active"> Nested Two</RouterLink>
        </li>
        <hr class="my-4" />
        <RouterView></RouterView>
    </ul>
</template>

<style scoped></style>

views/nested경로 안에 NestedOneView.vueNestedTwoView.vue를 생성한다.

one.vue

<template>
    <div class="card">
        <div class="card-header">Nested One</div>
        <div class="card-body">
            <h5 class="card-title">Special title treatment</h5>
            <p class="card-text">With supporting text below as a natural lead-in to additional content.</p>
            <a href="#" class="btn btn-danger">Go somewhere</a>
        </div>
    </div>
</template>

two.vue

<template>
    <div class="card">
        <div class="card-header">Nested Two</div>
        <div class="card-body">
            <h5 class="card-title">Special title treatment</h5>
            <p class="card-text">With supporting text below as a natural lead-in to additional content.</p>
            <a href="#" class="btn btn-primary">Go somewhere</a>
        </div>
    </div>
</template>

Children

그리고 중첩된 라우터를 설정한다.

router/index.js

{
  path: '/nested',
  name: 'Nested',
  component: NestedView,
    children: [
    	{
      	path: 'one',
        name: 'NestedOne',
        component: NestedOneView
      },
      {
      	path: 'two',
        name: 'NestedTwo',
        component: NestedTwoView
      }
    ]
}

/nested 선언 객체 안에 children 속성을 추가하여 배열 값으로 똑같이 라우터를 집어넣는다. children일 때는 path에 /가 부모를 통해 자동으로 붙기 때문에 빼도록 한다. /가 붙으면 절대경로가 되어버리니까 주의하자.

/nested/one, /nested/two로 라우터가 연결되어 이동할 수 있다. 고정 레이아웃은 페이지가 이동되어도 유지하고, 페이지 컴포넌트의 컨텐츠 영역이 다르게 렌더링이 가능하게 활용할 수 있다.

그리고 Vue에서는 라우터 이동할 때 /를 안붙이면 현재 부모 URL 기준으로 페이지가 이동되기 때문에

children으로 맵핑 된 NestedOneView, NestedTwoViewNestedView.vue/nested경로가 자동으로 붙어 /nested/one, /nested/two페이지로 이동할 수 있다.

이 방법이 혼란스럽다면 절대경로 URL

/nested/one, /nested/two로 이동선언을 하면 된다. 아래 코드 참고

<!-- 현재 페이지 컴포넌트가 상위라면 하위 URL은 부모 path와 슬래쉬를 생략 -->
<li class="nav-item">
  <RouterLink to="one" class="nav-link" active-class="active"> Nested One</RouterLink>
</li>
<li class="nav-item">
  <RouterLink to="two" class="nav-link" active-class="active"> Nested Two</RouterLink>
</li>

<!-- 확실한 다른 방법으로는 -->
<li class="nav-item">
  <RouterLink to="/nested/one" class="nav-link" active-class="active"> Nested One</RouterLink>
</li>
<li class="nav-item">
  <RouterLink to="/nested/two" class="nav-link" active-class="active"> Nested Two</RouterLink>
</li>

그리고 /nested라는 경로에 아무것도 없는데 여기에 메인(홈)을 구성하고 싶다면 아래와 같이 구성할 수 있다.

routes/index.js

children 값에 상단에 추가한다.

{
  path: '/nested',
	name: 'Nested',
  component: NestedView,
  children: [
  	{
    	path: '',
      name: 'NestedHome',
      component: NestedHomeView
    },
    {
    	path: 'one',
      name: 'NestedOne',
      component: NestedOneView
    },
    {
    	path: 'two',
      name: 'NestedTwo',
      component: NestedTwoView
    }
  ]
}

views/nested/NestedHomeView.vue

<script setup></script>

<template>
    <div class="card">
        <div class="card-header">Nested Home</div>
        <div class="card-body">
            <h1 class="card-title">Nested routes home</h1>
        </div>
    </div>
</template>

<style scoped></style>

router.replace

router.push와 같은 역할을 하지만 차이점이 있다.

새로운 히스토리 항목에 추가하지 않고 탐색하는 것이 replace함수이다.

사용 방식은 두 가지가 있는데

선언 방식

<router-link :to=".." replace>

프로그래밍 방식

router.replace(...)

router.push 함수에 replace: true 속성을 추가하여 동일하게 동작도 할 수 있다.

router.push({
  path: '/',
  replace: true
}})

// 같은 의미
router.replace({ path: '/' })

router.go(n)

이 함수는 window.history.go() 함수와 비슷하게 히스토리 스택에서 앞, 뒤로 이동하며 매개 변수에는 음수/양수 값을 넣으며 조정한다.

-1 == history.back() 뒤로가기

1 == history.forward() 앞으로가기

n == 지정한 만큼 이동

지정한 값만큼 이동할 기록이 없으면 실패함

profile
Full-stack Engineer. email - corner3499@kakao.com,

0개의 댓글