본문 바로가기

Vue.js

[Udemy Vue 완벽가이드 Section8] 103. 잠재적인 문제점

 

 

App.vue 컴포넌트를 보면, ActiveElement 컴포넌트와 KnowledgeBase 컴포넌트를 렌더링하고 있다.

<!--App.vue 컴포넌트-->
<template>
  <div>
    <active-element
      :topic-title="activeTopic && activeTopic.title"
      :text="activeTopic && activeTopic.fullText"
    ></active-element>
    <knowledge-base :topics="topics" @select-topic="activateTopic"></knowledge-base>
  </div>
</template>

<script>
export default {
  data() {
    return {
      topics: [
        {
          id: 'basics',
          title: 'The Basics',
          description: 'Core Vue basics you have to know',
          fullText:
            'Vue is a great framework and it has a couple of key concepts: Data binding, events, components and reactivity - that should tell you something!',
        },
        {
          id: 'components',
          title: 'Components',
          description:
            'Components are a core concept for building Vue UIs and apps',
          fullText:
            'With components, you can split logic (and markup) into separate building blocks and then combine those building blocks (and re-use them) to build powerful user interfaces.',
        },
      ],
      activeTopic: null,
    };
  },
  methods: {
    activateTopic(topicId) {
      this.activeTopic = this.topics.find((topic) => topic.id === topicId);
    },
  },
};
</script>

 

 

App.vue에서는 이 두 props를 activeTopic에 기반해 active-element에 제공한다.

activeTopic은 컴포넌트 내부 데이터이고, 초깃값은 null이다.

activateTopic 메서드가 트리거되면, activeTopic을 topic 배열에 있는 두 topic 중 하나로 설정한다.

 

activateTopic은 topicId를 수신하고, 해당 id를 topics 배열에 포함된 두 topic 중 하나를 식별하는데 사용한다.

 

 

select-topic 이벤트는 knowledge-base 컴포넌트에서 발생(emit)한다.

select-topic 이벤트가 발생하면 activateTopic 메서드가 트리거된다.

그리고 knowledge-base 컴포넌트에 topcis 데이터 프로퍼티가 props로 전부 전달된다.

<knowledge-base :topics="topics" @select-topic="activateTopic"></knowledge-base>

 

 

ActiveElement.vue 컴포넌트는 꽤 단순하다.

topicTitle, text가 있고, 이 두 데이터가 props로 수신된다.

<template>
  <section>
    <h2>{{ topicTitle }}</h2>
    <p>{{ text }}</p>
  </section>
</template>

<script>
export default {
  props: ['topicTitle', 'text'],
};
</script>

 

 

KnowledgeBase.vue 컴포넌트를 살펴보자.

<template>
  <section>
    <h2>Select a Topic</h2>
    <knowledge-grid :topics="topics" @select-topic="$emit('select-topic', $event)"></knowledge-grid>
  </section>
</template>

<script>
export default {
  props: ['topics'],
  emits: ['select-topic'],
};
</script>

props로는 'topics'가 하나 있고, select-topic 이벤트를 emit 하겠다고 선언되어 있다.

 

하지만, 여기에 작은 문제가 있다.

KnowledgeBase.vue 컴포넌트를 보면, KnowledgeGrid 컴포넌트에 topics를 전달하고 있다.

그리고 KnowledgeBase.vue 컴포넌트로부터 select-topic을 emit하지만, KnowledgeGrid컴포넌트에서 select-topic 이벤트를 emit할 때, KnowledgeBase에서 'select-topic' 이벤트를 emit한다.

 

즉, KnowledgeBase.vue는 그저 App.vue - KnowledgeGrid.vue 컴포넌트 사이에서 전달 역할만 하고 있다. 

topics를 KnowledgeGrid.vue에 props로 전달하고, KnowledgeGrid.vue에서 select-topic 이벤트를 emit하면 App.vue에 전달한다.

KnowledgeBase.vue는 자체 로직이 전혀 없다.

 

이런 컴포넌트가 아주 특이한건 아니다. 

어쩌면 이 컴포넌트에 포함하고싶은 특정 마크업이 있거나, 특정 스타일이 있어서일수도 있다.

이렇게 단순히 전달만하는 컴포넌트가 Vue앱에서 이상한건 아니다.

 

 

이번에는 KnowledgeGrid.vue를 한번 보자.

<template>
  <ul>
    <knowledge-element
      v-for="topic in topics"
      :key="topic.id"
      :id="topic.id"
      :topic-name="topic.title"
      :description="topic.description"
      @select-topic="$emit('select-topic', $event)"
    ></knowledge-element>
  </ul>
</template>

<script>
export default {
  props: ['topics'],
  emits: ['select-topic']
};
</script>

KnowledgeGrid.vue도 topics를 사용한다.

이 컴포넌트에서는 topics를 자식 컴포넌트에 단순 전달만 하는건 아니고, topics를 직접 이용한다.

하지만 여기서도 select-topic을 emit하고, 전달도 여전히 일어나고 있다.

 

 

이번에는 KnowledgeElement.vue 컴포넌트를 보자.

<template>
  <li>
    <h3>{{ topicName }}</h3>
    <p>{{ description }}</p>
    <button @click="$emit('select-topic', id)">Learn More</button>
  </li>
</template>

<script>
export default {
  props: ['id', 'topicName', 'description'],
  emits: ['select-topic'],
};
</script>

컴포넌트를 보면, 버튼을 클릭했을 때, select-topic이 emit된다. 여기서 select-topic이라는 커스텀 이벤트가 발생되고있다.

 

KnowledgeGrid.vue와 KnowledgeBase.vue는 단지 해당 커스텀 이벤트(select-topic)를 App.vue로 전달만 할 뿐이다.

커스텀이벤트는 두 컴포넌트를 거쳐 전달되고, topcis도 두 컴포넌트 중, 적어도 하나의 컴포넌트를 거쳐서 전달된다.

 

전부 작동도 잘되고 잘못 작성한 코드라고 할 수 없다.

이런 식으로도 props와 event가 작동하고 연결된다는 점을 알면 좋다.

 

하지만 아직도 남은 문제가 하나 있다. 바로, 불필요한 전달 단계를 거쳐야한다는 문제.

KnowledgeBase.vue가 이 props와 이벤트 발생처리에 관여할 필요는 없다. 둘 다 컴포넌트 내부에서 사용되지도, 생성되지도 않으므로.

그저 KnowledgeGrid.vue에 연결하는데만 쓰인다.

 

Vue가 이 문제를 해결해준다.

 

 

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