[Vue3실강] 10강 Vue Router 최종

youngseo·2022년 6월 7일
0
post-thumbnail

Vue Router 최종

1. Header가 있는 페이지와 없는 페이지 만들기.

(components들을 연결하는 옵션을 사용합니다.)

🐥Named Routers

const routes = [
  {
    path: '/user/:username',
    name: 'user',
    component: User
  }
]

각각의 페이지를 routes에 지정을 할 때 name을 지정하면 이름을 활용해 조금 더 편리하게 사용을 할 수 있습니다.

router-link명명된 경로에 연결하려면 구성 요소의 to소품 에 개체를 전달할 수 있습니다 .

<router-link :to="{ name: 'user', params: { username: 'erina' }}">
  User
</router-link>

🐥Named Views

페이지를 구분할 때 사용할 컴포넌트들을 조금 더 명확하게 지정해줄 수 있습니다.

이전 시간에 어떤 페이지로 이동하더라도 header가 유지되도록 만들었습니다. 그런데 특정한 페이지에서는 이 header가 보이지 않도록 만들어줄 수 있습니다.

App.vue

<template>
  <TheHeader />
  <RouterView />
</template>

현재 <TheHeader />가 전역화되어 사용되고 있습니다.

또한 RouterView를 통해 페이지가 바뀔때마다 렌더링되는 위치를 지정해놓았습니다.

하지만 TheHeader의 경우 페이지가 바뀌는 것과 상관 없이 위에 박혀있기 때문에 페이지가 바뀌더라도 위에 위치를 하게 되는 것입니다.

따라서 TheHeader도 렌더링에 따라 바뀌는 구조를 만들어보려고 합니다.

1. RouterView name=""

App.vue

<template>
  <RouterView name="TheHeader" />
  <RouterView />
</template>

<TheHeader />대신에 <RouterView />를 이용합니다. 또한 name을 부여해줍니다.

이제 <TheHeader />는 존재하지 않으며 이름이 있는 <RouterView />와 이름이 없는 <RouterView />가 존재하게 됩니다.

✅코드 예시

2.router의 index.js

페이지 관리에 대한 내용이 들어 있는 router의 index.js에서 TheHeadear를 가져옵니다.

index.js

import { createRouter, createWebHistory } from 'vue-router'
import TheHeader from '~/component/TheHeader.vue'import Home from './Home.vue'
import Movie from './Movie.vue'
import About from './About.vue'
import AboutName from './AboutName.vue'
import NotFound from './NotFound.vue'

export default createRouter({
  history: createWebHistory(),
  routes: [
    {
      name: 'mainpage',
      path: '/',
      components: Home✅복수형태로 변경
    },
    {
      path: '/movies/:heropy',
      component: Movie
    },
    {
      path: '/about',
      component: About,
      children: [
        {
          path: 'name',
          component: AboutName
        }
      ]
    },
    {
      path: '/:notFound(.*)*',
      component: NotFound
    }
  ]
})

3. components

main페이지와 movie페이지에서만 헤더가 존재하도록 해보겠습니다.

mainpagemovie페이지의 component를 복수형태인 components로 바꾸어주고 Home대신 객체를 할당합니다.

    {
      name: 'mainpage',
      path: '/',
        //✅1. 복수형태로 변경
        //✅2. Home대신 객체데이터할당
      components: {
        'TheHeader': TheHeader,
        default: Home
      }
    },
  • components로 바꾸고 컴포넌트를 여러개를 사용하겠다는 의미로 바꾸었습니다.
  • 그리고 객체데이터 안에 각각의 사용할 컴포넌트의 이름을 부여합니다.
  • (TheHeader에는 TheHeader을, default에는 Home을 부여합니다.)

이제 TheHeader라는 이름을 가진 컴포넌트는 App.vue<RouterView name="TheHeader" /> 에 출력이 되고, default인 Home은 이름을 지정하지 않은 <RouterView />에 출력이 되게 됩니다.

App.vue

  <RouterView name="TheHeader" /> =>TheHeader, 이름 매칭
  <RouterView /> =>default

이렇게 쓰고 싶은 페이지에서만 Header가 출력되도록 설정해줄 수 있습니다.

마찬가지로 movie페이지도 설정을 해줍니다.

{
  path: '/movies/:heropy',
    components:{ //순서는 상관 없습니다.
      default: Movie,
        TheHeader
    }
},

※객체데이터는 순서가 존재하지 않습니다.

  • 순서대로 작성을 했을 뿐이지 실제로 조회할때는 순서대로 조회하는 것이 아닌 key에 해당하는 값을 조회하는 것입니다.

Movie페이지와 Home페이지에만 TheHeader가 생긴 것을 확인할 수 있습니다.

🐥redirect

index.js

{
  path: '/:notFound(.*)*',
    component: NotFound,
      //이상한 주소로 이동하는 경우 about페이지로 튕겨줍니다.
    redirect: './about'
}

redirect란 페이지를 팅겨서 다른 페이지로 보내는 기능입니다. 특정한 페이지가 보수중인 경우,임시로 사용할 페이지로 팅겨주는 용도로 사용할 수 있습니다.

매칭될수 없는 이상한페이지로 이동시 about페이지로 이동하게 됩니다.

🐥 Meta FieldsNavigation guards

  • 페이지에 메타정보(기본이 되는 정보)를 담아두는 옵션입니다.
  • 대표적으로 Navigation guid에서 활용을 할 수 있습니다.
  • 네비게이션 가드는 모든 페이지에 접속하기 전, 또는 모든페이지에서 빠져나올 때 그런 특정한 상황을 제어할 수 있습니다.
  • 네비게이션 가드에서 유용하게 사용할만한 것이 Global Before Guards입니다.(모든 페이지에 접속하기 이전에)
  • 보통 로그인 여부를 확인해서 로그인을 했을 때만 접속가능한 페이지를 걸러내는 용도로 사용이됩니다.

1. Meta Fields

페이지에 대한 정보 확인하기

About.vue

<template>
  <h1>About!</h1>
  <RouterLink to="/about/name">
    Name~
  </RouterLink>
  <RouterView />
</template>
<script>
export default {
  created() {
    //$this.route에서 페이지에 대한 정보를 확인할 수 있습니다.
    console.log(this.$route)
  }
}
</script>

현재 meta는 비워져 있는 것을 확인할 수 있습니다

메타에 정보 넣기

route>index.js

    {
      path: '/about',
      component: About,
      meta: {auth:true}, //✅
      children: [
        {
          path: 'name',
          component: AboutName,
          redirect: '/'
        }
      ]
    },

meta값이 채워진 것을 확인할 수 있습니다. 이와 같이 Meta Fields는 어떠한 페이지의 특정 정보를 담는 용도입니다.

🐥풀어서 이해하기
사용자가 우리 어플리케이션에 접속을 했을 때를 가정해보도록 하겠습니다. 메인페이지와 검색페이지는 누구나 접속이 가능하지만 상세정보 페이지는 로그인이 필요한 상황입니다.
여기서 상세정보 페이지에 접속하기 전 검문서 역할을 하는 것이 router guard이며 로그인 정보를 구분하는 것이 바로 meta정보입니다.

2. Navigation guards

Global Before Guards

  • from: 어디에서 출발했느냐에 대한 정보를 들고 있는 매개변수
  • to: 어디로 갈 것이냐에 대한 정보를 들고 있는 매개변수
const router = createRouter({ ... })
//
router.beforeEach((to, from) => {
  // ...
  // explicitly return false to cancel the navigation
  return false
})

Navigation gaurds의 경우 보통 로그인을 확인해서 로그인을 한 경우에만 특정페이지에 접근 가능하도록 만들어줄 떄 유용합니다.

2-1 router Guards설정

routes>guards.js
guards.js라는 새로운 파일을 만들어줍니다.

//router는 index.js에서 createRouter을 실행한 결과가 내보내기를 통해 빠져나온 것을 담은 것입니다.
import router from './index.js'

router.beforeEach((to) => {
  console.log(to)

  return true})
  • router.beforeEach에서 true,false값을 반드시 return해줘야합니다.

2-2 router Guard 연결

main.js

import { createApp } from 'vue'
import router from './routes'
import '~/routes/guards'import App from './App.vue'

createApp(App)
  .use(router)
  .mount('#app')

guards.js

import router from './index.js'

router.beforeEach((to) => {
  console.log(to)

  return true
})

Main 페이지에서 About페이지로 접근한 후 콘솔에 출력된 결과를 보면 router gaurd to가 들고있는 정보가 about페이지에서 확인했던 this.$route정보와 똑같이 생겼다는 것을 알 수 있습니다.

즉, router guards의 to라는 매개변수가 들고 있는 정보는 내가 접근하려는 그 페이지에 대한 정보를 담은 객체입니다.

또한 이 객체에는 meta정보가 들어있으며 그 값이 true인지 false인지를 구분할수 있습니다.

그럼 이번에는 meta정보가 들고 있는 auth값을 출력해보도록 하겠습니다.

guards.js

import router from './index.js'

router.beforeEach((to) => {
  console.log(to.meta.auth)

  return true
})

위와 같이 about페이지에 접근을 하면 true가 잘 출력되는 것을 확인할 수 있습니다. 따라서 about페이지에 접근하기 위해서는 로그인 정보가 필요하다는 것을 알 수 있습니다(참고로 다른 페이지에서의 출력결과는 undefined입니다)

즉, Global Before Guards를 이용해 페이지에 넘어가기 전 로그인 정보가 필요한지 아닌지를 확인할 수 있습니다.

2-3 로그인을 한 상황과 아닌 상황을 구분하는 로직짜기

로그인에서 많이 사용하는 방법은 로컬스토로지입니다.

로컬스토로지에 임의로 currentUser값을 설정해줍니다. 로컬스토로지에의 정보는 json정보(문자데이터)이기 때문에 자바스크립트에서 사용하기 위해서 JSON.pars를 해줘야합니다.

1) 우리가 만든 currentUser를 한번 조회해보겠습니다.

guards.js

import router from './index.js'

router.beforeEach((to) => {
  console.log(to.meta.auth)
  console.log(JSON.parse(localStorage.getItem('currentUser')))

  return true
})

이렇게 받아온 정보의 name이 있으면 로그인을 한 정보가 맞구나~ 하고 판단을 할 수 있습니다.

2) 조건설정

guards.js
router의 beforeEach는 모든페이지에 접근하기 직전입니다. 이 모든 페이지에 접근할 때 to.meta.auth가 true인 경우를 조건으로 설정하도록 하겠습니다.

import router from './index.js'

router.beforeEach((to) => {
  if(to.meta.auth) { //true인 경우
    
      //currentUser에 name이 있으면 로그인 한 사람입니다, 
    //{}의 경우 null을 대비합니다.(json.parse떄문에 '{}'로합니다.)
    const {name} = JSON.parse(localStorage.getItem('currentUser') || '{}')
    if(name) {
      // name이 있으면 통과~!
      return true
    } else {
      //name이 없으면 메인페이지로 가라
      //(login페이지로 보내야하는데 없으니 메인페이지 보통은 '/login'으로 보냅니다.)
      return '/'
    }
  }

  return true
})

현재 로컬스토로지에 로그인 정보가 있기 때문에 about페이지가 잘뜨는 것을 확인할 수 있습니다.

로컬스토로지에 로그인 정보를 지우면, 메인페이지로 튕겨나오는 것을 확인할 수 있습니다.


🐥Scroll Behavior

1. scroll Behavior실습을 위한 환경조성

App.vue


<style>
#app {
  height: 3000px;
}
</style>

TheHeader.vue

<style scoped>
  header {
    position: fixed;
    top: 0;
    left: 0;
  }
</style>

메인페이지에서 스크롤을 내린 후 다른 페이지로 이동하면, 페이지는 이동하더라도 스크롤 위치는 그대로인 것을 확인할 수 있습니다.

이는 싱글페이지어플리케이션에서 발생하는 문제입니다. 이를 해결하기 위해 라우터에서 Scroll Behavior를 제공합니다.

2. Scroll Behavior설정

index.js

export default createRouter({
  history: createWebHistory(),
  ✅scrollBehavior: () => ({top: 0}),
 ...
})

뷰 라우터를 도입한다면 필수적으로 Scroll Behavior를 설정한다고 생각하는 것이 좋습니다.

0개의 댓글