본문 바로가기

데일리 공부 기록

hands on vue3 - <router-link to>가 안먹는다? 그 이유는 렌더링 특징 때문이다.

728x90

[목표]

<router-link to> 태그를 이용하여 URL 이동을 하려고 한다.

그런데 URL은 다르지만 컴포넌트는 같다.

 

예를 들어 다음과 같은 상황이다.

팀원을 보여주는 컴포넌트이다.

현재 Team1의 팀원들을 보여주고 있다.

 

보여주는 컴포넌트 파일은

TeamMembers.vue이다.

 

같은 vue 내에서

Team2의 팀원들을 보여주고싶다.

 

보여주는 컴포넌트 역시 Team1과 같다.

 

이럴 때는

컴포넌트 내의 요소들이 변화하지 않는다.

 

다음 코드를 보며 이해하자

[TeamMembers.vue]

<template>
  <section>
    <h2>{{ teamName }}</h2>
    <ul>
      <user-item
        v-for="member in members"
        :key="member.id"
        :id="member.id"
        :name="member.fullName"
        :role="member.role"
      ></user-item>
    </ul>
    <router-link to="/teams/t2">Go To Team2</router-link>
  </section>
</template>

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

export default {
  inject: ['teams', 'users'],
  components: {
    UserItem
  },
  data(){
    return{
      members:[],
    };
  },
  methods:{

  },
  created(){
    let param = this.$route.params.teamsId;
    let result = this.teams.find((element) => {
      for(let i in element.members){
        return element.id == param;
      }
    });       

    for(let i in result.members){
      this.users.find((element)=>{
        if(element.id == result.members[i]){
          this.members.push(element);
        }
      });
    }
  },
};
</script>

<style scoped>
section {
  margin: 2rem auto;
  max-width: 40rem;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
  padding: 1rem;
  border-radius: 12px;
}

h2 {
  margin: 0.5rem 0;
}

ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
</style>

소스를 보면 created에 

사용할 데이터들을 처리한다.

URL을 이동했다 하더라도

같은 컴포넌트라면 처음부터

렌더링을 다시 하지 않는다.

 

원래 의도대로 라면 

Destroy 했다가 Create를 하려고 했지만

router인가 vue인가의 특징 때문에

 

이미 이전과 같다면

캐시에 저장된 데이터를 보여준다.

또한 렌더링을 하지 않는다. 

 

그러면 어떻게 해야할까?

 

TeamMembers.vue 내에서

라우터가 이동되는 걸 확인하고 

데이터를 변경해야되지 않을까?

 

 


[TeamMembers.vue]

<template>
  <section>
    <h2>{{ teamName }}</h2>
    <ul>
      <user-item
        v-for="member in members"
        :key="member.id"
        :id="member.id"
        :name="member.fullName"
        :role="member.role"
      ></user-item>
    </ul>
    <router-link to="/teams/t2">Go To Team2</router-link>
  </section>
</template>

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

export default {
  inject: ['teams', 'users'],
  components: {
    UserItem
  },
  data(){
    return{
      members:[],
    };
  },
  methods:{
    changeData(){
      let param = this.$route.params.teamsId;
      let result = this.teams.find((element) => {
        for(let i in element.members){
          return element.id == param;
        }
      });       

      for(let i in result.members){
        this.users.find((element)=>{
          if(element.id == result.members[i]){
            this.members.push(element);
          }
        });
      }
      }
  },
  created(){
    this.changeData();
  },
  watch:{
    $route(){
      this.changeData();
    }
  }
};
</script>

<style scoped>
section {
  margin: 2rem auto;
  max-width: 40rem;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
  padding: 1rem;
  border-radius: 12px;
}

h2 {
  margin: 0.5rem 0;
}

ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
</style>

 

watch를 사용하여

라우터가 변화할 때마다

다시 데이터를 얻어주는 걸로 해결할 수 있었다.

 

요즘 Vue를 하면서

렌더링의 이해에 대한 중요성을 느끼고 있다.