Vue.js의 Component, props, emit

2 minute read

Vue의 Component 개발 방식과, props와 emit에 대해 알아보자

Vue.js 의 Component 개발 방식, 그리고 그 장단점

Component

React와 비슷하게 Vue.js도 Component 방식의 개발을 하고 있다. Vue에서, 컴포넌트는 본질적으로 미리 정의된 옵션을 가진 Vue 인스턴스이다.

Vue.component('todo-item', {
  template: '<li></li>',
  props: ['todo']
})

이렇게 컴포넌트 하나를 정의하고 나면, ‘todo’를 v-bind를 사용하여 각각의 컴포넌트에 전달할 수 있다.

<div id="app">
  <ol>
    <todo-item
      v-for="item in groceryList"
      v-bind:todo="item"
      v-bind:key="item.id">
    </todo-item>
  </ol>
</div>

<script>
  Vue.component('todo-item', {
    props: ['todo'],
    template: '<li></li>'
  })

  var app = new Vue({
    el: '#app',
    data: {
      groceryList: [
        { id: 0, text: 'Vegetables' },
        { id: 1, text: 'Cheese' },
        { id: 2, text: 'Whatever else humans are supposed to eat' }
      ]
    }
  })
</script>

그래서 뭐가 좋은건데?

그래서 컴포넌트 기반의 개발이 뭐가 좋을까??

장점

1. 재사용성

한번 잘 만들어진 컴포넌트는 앱의 어느 위치에서든지 불러와 다시 사용할 수 있다. 이를 통해 개발 속도가 상당히 빨라질 수 있다.

2. 캡슐화

컴포넌트를 메인 앱과 완전히 분리시킴으로써, 재사용성, 테스트 가용성, 신뢰성 등이 높아진다. 컴포넌트는 내부적인 동작에만 반을할 뿐, 어플리케이션의 상태에 관여하지 않기 때문이다. 따라서 컴포넌트 개발과 사용에 있어서 앱의 나머지 부분에 영향을 미칠지 걱정하지 않아도 된다.

3. 확장성

컴포넌트를 각각 확장할 수 있어야 한다. 이미 잘 만들어져있는 바퀴를 다시 처음부터 발명할 필요없이, 잘 만들어진거 가져다 쓰면 된다.

4. 단일파일 컴포넌트

이건 개인적 생각의 장점이긴 하지만, 한 파일 내에 템플릿, 스타일, 로직을 모두 넣을 수 있다는게 매우 좋아보인다.

단점

사실 단점은… 아직 잘 모르겠지만… 앱 개발 단계에서 컴포넌트를 나누고, 계획하는 단계가 필요한 것…? 공부해 가면서 단점을 찾으면 추가해야겠다.

Props 와 Events Emitting

컴포넌트 기반의 개발을 하면 컴포넌트가 여러개 생기게 되고, 이들간의 커뮤니케이션 방법도 필요하다. Vue.js는 단방향 데이터 흐름이다.

자녀 컴포넌트의 프로퍼티를 이용해 부모 컴포넌트 측의 데이터를 전달한다.

<div id="app">
  <ol>
    <todo-item
      v-for="item in groceryList"
      v-bind:todo="item"
      v-bind:key="item.id">
    </todo-item>
  </ol>
</div>

<script>
  Vue.component('todo-item', {
    props: ['todo'],
    template: '<li></li>'
  })

  var app = new Vue({
    el: '#app',
    data: {
      groceryList: [
        { id: 0, text: 'Vegetables' },
        { id: 1, text: 'Cheese' },
        { id: 2, text: 'Whatever else humans are supposed to eat' }
      ]
    }
  })
</script>

하지만 반대로 자녀 컴포넌트에서 부모 컴포넌트로의 데이터 전달은 불가능하다. 대신 이벤트를 전달하는 방식으로 커뮤니케이션을 한다.

<Child v-on:typed="onTyped"></Child>

<script>
Vue.component('NameForm', {
  el: '#child',
  methods: {
    onClick: function() {
      this.$emit('typed');
    }
  }
});
</script>

Child 컴포넌트는 onClick 메서드에서 ‘typed’ 이벤트를 발생시킨다. 그럼 부모쪽에서는 typed 이벤트에 연결된 onTyped 메서드를 실행할수 있다.


이런 식으로 컴포넌트간의 상태를 공유할 수 있지만, 앱의 규모가 커지게 되면 상태 관리가 상당히 어렵게 될 것이다… 그래서 더 공부하다 보면 결국 리액트를 공부할 때처럼 Redux와 비슷한 Vuex를 쓰게 될 것 같긴하다… 나는 리액트 공부를 열심히 해야겠다.

Updated: