Vue.js Routing

강정우·2023년 4월 4일
0

vue.js

목록 보기
23/72
post-thumbnail

라우팅

  • 라우팅은 우리의 URL을 누군가에게 공유하였을 때 화면을 보면 더 정확하게 알 수 있다.
    또는 어떠한 작업을 해 놓았다고 가정할 때 URL이 메인페이지 밖에 없다면 다시 처음부터 일련에 행동들을 다시 수행해야한다는 단점이 있다. 이를 방지하고자 라우팅이라는 기능이 존재한다.

  • 또 URL과는 interact한 상태여야 위치판 페이지를 나타내는 URL을 다른 사람과 공유할 수 있다.

vue-router

  • vue-router를 사용하면 브라우저에서 JavaScript로 URL의 변경 사항을 관리하고 동일한 싱글 페이지 애플리케이션 상에 URL이 변경되거나 해당 URL을 기반으로 화면에 이를 로드해준다.

  • 또한 URL을 변경할 수도 있다. 애플리케이션에서 다른 위치로 이동할 때 URL이 해당 위치를 반영할 수 있다.

npm install --save vue-router

// 최신버전은
npm install --save vue-router@next

사용법

main.js

const router = createRouter({
	history:createWebHistory(),
    routes:[
    	{path : '/url', 컴포넌트},
        {path : '/url', 컴포넌트},
    ]
})

app.use(router);
  • 인수로 지원하고자하는 URL등을 설정할 수 있다.
    라우터 생성을 위해 JS 객체를 입력하는데

  • 해당 객체에는 두 가지 중요한 옵션을 설정할 수 있다.

1. routes

  • 여기서는 모든 라우트이자 경로 즉 우리가 지원하고자 하는 여러 URL을 등록한다.

  • 보통 배열이 들어가는데 대부분의 경우 앱에서 하나 이상의 라우트를 지원하고자 하기 때문이다.

  • 또 해당 배열 안에는 JS 객체가 들어가야한다.
    모든 객체는 하나의 라우트에 해당하며 라우트에 대한 구성이 있어야 한다. 모든 라우트에 대해 설정하는 중요한 옵션으로, 경로 path 옵션이 있다. path는 URL에서 도메인의 뒷부분에 해당하며 라우터가 어떤 컴포넌트를 로드해야 하는지 알려 주는 역할을 한다.

  • 컴포넌트 : 사용자가 /url 경로의 도메인을 방문했을 때 로드할 컴포넌트를 정의

2. history

  • 이 옵션을 통해서 라우터에게 본 앱의 라우팅 히스토리 관리 방법을 알려 줄 수 있다.

  • 사용자가 다른 곳을 클릭하면 다른 페이지로 넘어가고 해당 페이지가 브라우징 히스토리에 등록되도록 하는 방식을 설정할 수 있다. 사용자가 뒤로가기 버튼을 누를 때는 히스토리를 통해 라우터가 이전 페이지를 알 수 있다.

use()

  • Vue 앱에 다음과 같은 라우트의 router 상수가 있음을 알려야 하는데 아래 app 상수에서 use 메서드를 통해 이 작업을 할 수 있다.

  • use는 내장 메서드로 Vue 앱에 서드 파티 패키지와 다른 기능을 연결해 주는 역할을 한다.

  • router를 전달하면 Vue 앱이 이 router를 인식하게 된다.

  • 그럼 이제 해당 컴포넌트를 어디서 렌더링할 지정해보자.

<route-view>

  • 이 컴포넌트가 이 위치로 선택된 라우트 대상인 컴포넌트가 로드되어야 한다고 Vue 앱에게 알리는 플레이스홀더의 역할을 한다.

<router-link>

  • 기본적으로는 <a> 와 유사하다.
    다른 페이지를 로드해서 전체 앱을 새로고침하여 현재 상태를 잃게 되는 특별 앵커 태그가 아니라 브라우저 기본값으로 다른 페이지가 로드되는 것을 막고 Vue 라우터를 통해 사용자가 클릭한 링크를 분석하여 알맞은 컴포넌트를 로드하며 URL을 업데이트하는 특별 앵커 태그이다.

  • 또한 내부적으로 <slot>을 사용하기 때문에 내부에 html element 또한 전달가능하다.

<router-link to='/teams'> <router-link>

<router-link :to="'/teams/'+id"> <router-link>
  • 또 중요한 속성은 to 인데 여기에는 여러 값들이 들어갈 수 있다. 하지만 가장 흔한값은 문자열로 구현하는 것이다.
    이때 경로는 routes 구성을 통해 지원하고 있는 라우트여야한다. 이때 여기에 들어가야할 값이 route 구성객체인 name 이여야한다.

  • 이때 css를 먹이고 싶다면 <a> 이기 때문에 그냥 a {} 이런식으로 css를 부여하면 된다.

  • 또 장점이 Vue 라우터가 router-link-active, router-link-exact-active라는 클래스를 자동으로 부여하는데 현재 선택된 링크, 즉 현재 활성 상태인 라우트에 대해서만 추가된다.
    이를 통해 따라서 선택한 링크를 기반으로 스타일을 지정할 수 있고 이를 통해 현재 사용자가 있는 라우트에 대한 피드백을 제공할 수 있다.

  • 참고로 router-link-active나 router-link-exact-active말고 그냥 내가 설정한 값으로 설정하고 싶다면 main.js의 CreateRouter에서 linkActiveClass 로 속성값으로 내가 지정한 값을 active할 때 추가해줄 수 있다.

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/teams', component: TeamsList }, // our-domain.com/teams => TeamsList
    { path: '/users', component: UsersList },
  ],
  linkActiveClass:'원하는 값'
});
  • 여기서 exact가 왜 나오냐면 nested route에 대비하여 나온것이다.

사용자 이동

  • 리엑트 라우트와 비슷하다. 리엑트 라우트 최신 버전에서는 naviagate가 아닌 route를 import해와서 스택구조에 push하였는데 이도 마찬가지이다.
this.$router.push('/url');
this.$router.back();
this.$router.forward();

동적 세그먼트

  • path에서 :이 바로 dynamic path sagment가 된다.
const router = CreateRouter({
	history : createWebHistory(),
    routes : [
    	{path : '/teams/new', component : New},
    	{path : '/teams/:teamId', component : TeamMembers},
        ...
    ],
    linkActiveClass : 'active'
})
  • 이때 순서가 중요한데 exact기능이 routes에 따로 없기에 순서가 매우 중요하다. "하드코딩"될 문자열이 오고 제일 마지막에 동적 세그먼트가 와야한다.
export default {
  inject : ['' ,'', ...],
  component : {
    컴포넌트
  },
  data () {
    return {
      
    }
  },
  created(){
    this.$route.path  // 여기서는 /teams/t1 임 (ps.173)
    this.$route.params.동적URL // 이걸 상수에 담아 로직을 작성
    const teamId = this.$route.params.teamId
    const selectedTeam = this.teams.find(team=>team.id === teamId)
    const members = selectedTeam.members;
    const selectedMembers = [];
    for(const member of members){
      const selectedUser = this.users.find(user=>user.id === member)
      selectedMember.push(selectedUser)
    }
    ...
  }
}

router vs route

  • router는 main이나 router 객체를 생성한 곳, route는 router를 통해 로드된 컴포넌트에서 route에 접근하기 위해 사용하는 객체

path vs params

  • route는 다양한 정보에 액세스하게 해주는데 그중 path는 페이지를 로드에 해당하는 경로이다.

  • params는 페이지 로드에 사용된 모든 라우트 매개변수를 갖고 있다.
    여기서 라우트 매개변수는 CreateRoute에서 (동적세그먼트 코드) : 으로 시작하는 모든 것을 라우트 매개변수라고 한다. 즉, 위의 코드에서는 teamId가 되는 것이다.

watcher로 매개변수 데이터 업데이트

  • 사실 동적으로 데이터를 가져오려면 위처럼 라이프 사이클을 이용하여 created할 때 컴포넌트를 생성한다. 그런데 다른 <a>를 클릭했다고 로드된 컴포넌트를 전부 버리고 새로 만들진 않는다.

  • 페이지 탐색 시 Vue 라우터는 로드된 컴포넌트를 파기하고 새로 구축하지 않는다. URL이 바뀔 때마다 파기하고 새로 구축하기보다 캐시에 저장하는 것이 훨씬 효율적이기 때문이다.
    바로 여기서 위와같은 문제가 일어나는데 이를 해결하기위해 자세히 봐야할 요소가 바로 $route이다.

  • 로드한 라우트에 대한 최신 정보를 담고 있는 데다가 URL이 바뀌면 업데이트되는 프로퍼티이기 때문이다.
    그래서 얘를 watcher로 주시하게 하면 된다.

methods : {
	컴포넌트를 업데이트하는 로직
},
created(){
	this.컴포넌트를 업데이트하는 로직(this.$route);
},
watch:{
	$route(newRoute){
    	this.컴포넌트를 업데이트하는 로직(newRoute);
    }
}

라우터 뿐만 아니라 컴포넌트에서도 렌더링하기

const router = CreateRouter({
	history : createWebHistory(),
    routes : [
    	{path : '/teams/new', component : New},
    	{path : '/teams/:teamId', component : TeamMembers, props:true},
        ...
    ],
    linkActiveClass : 'active'
})
  • props:true 속성값이 매우 중요하다. 라우터는 로드된 컴포넌트에 속성을 추가하지 않기 때문에 컴포넌트단에서 렌더링해줄 방법이 없기 때문이다. 그래서 props로도 인수를 받는 것이다.

  • 그래서 제일 마지막 동적 URL인 :teamId에 해당하는 부분이 프로퍼티로서 전달된다.

  • 그럼 이렇게하면 장점이 무엇인가 바로 라우팅에 묶여있지 않고 컴포넌트단위로 재활용이 가능해졌다는 것이다. 여기서는 teamId만 넘겨주면 어디서든 사용할 수 있게 된다.

<template>
    <ul>
      <user-item
        v-for="member in members"
      ></user-item>
    </ul>
</template>

<script>
import UserItem from '../users/UserItem.vue';

export default {
  inject: ['users', 'teams'],
  props: ['teamId'],
  components: { UserItem },
  data() {
    return {
      teamName: '',
      members: [],
    };
  },
  methods: {
    loadTeamMembers(teamId) {
      const selectedTeam = this.teams.find((team) => team.id === teamId);
      const members = selectedTeam.members;
      const selectedMembers = [];
      for (const member of members) {
        const selectedUser = this.users.find((user) => user.id === member);
        selectedMembers.push(selectedUser);
      }
      this.members = selectedMembers;
      this.teamName = selectedTeam.name;
    },
  },
  watch: {
    teamId(newId) {
      this.loadTeamMembers(newId);
    },
  },
};
</script>
  • 여기가 props:true로 얻어온 값

redirect, alias

const router = CreateRouter({
	history : createWebHistory(),
    routes : [
      	{path : '/', redirect : '/teams'},
    	{path : '/teams/new', component : New, alias:'/teams/add'},
    	{path : '/teams/:teamId', component : TeamMembers, props:true},
        ...
    ],
    linkActiveClass : 'active'
})
  • 말 그대로 / => /teams로 보내주는 역할을 한다.

  • alias는 component가 렌더링되었으면 하는 곳에 사용하면 된다. 하지만 단점은 URL이 바뀌지 않는다는 점이다.
    그것이 redirect와 alias의 차이점이다.

404(catchAll)

  • 해당 path 객체는 가장 밑에 작성하는 것이 좋다. 사용자의 입력은 무한하기 때문에 try-catch너낌으로 간다.
const router = CreateRouter({
	history : createWebHistory(),
    routes : [
      	{path : '/', redirect : '/teams'},
    	{path : '/teams/new', component : New, alias:'/teams/add'},
    	{path : '/teams/:teamId', component : TeamMembers, props:true},
        ...
        {path : '/:notFound(.*)', component : ErrorPage}
    ],
    linkActiveClass : 'active'
})
  • .* 는 정규표현식으로 Vue router가 지원하는 구문이다. 문자 조합은 어느 것이든 간에 이 경로의 값으로 사용되면 결국 로드한 이 라우트에 연결되어야 한다는 뜻이다.
    그래서 이 코드를 제일 마지막에 작성해야지 않그러면 다른 라우터를 덮어써버리기 때문이다.
profile
智(지)! 德(덕)! 體(체)!

0개의 댓글