ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Vue.js] 컴포넌트(Component), Props & Event
    Front-End(Web)/Vue 2021. 5. 26. 21:04
    반응형

    이번에는 비교적 친숙한! 뷰의 컴포넌트 개념에 대해 알아보고자 한다. React와 마찬가지로 화면을 구성하는 요소이다.

    현대의 모던 프레임워크들은 대부분 컴포넌트 개념을 차용하고 있기 때문에 뷰 역시 이를 기반으로 하고 있는 것 같다.

     

    컴포넌트와 관련된 개념과 영상이 많기 때문에 포스팅 분량이 길어지고 몇 부분으로 나눠질 것 같다.

     

    * 이 글은 캡틴판교님의 Vue.js 강의 및 블로그를 기반으로 학습한 내용을 정리하고 있습니다.


    💚 Vue 컴포넌트

    React와 마찬가지로 화면을 영역 단위로 쪼개서, 재사용 가능한 코드로 캡슐화하는 개념이다.

    뷰에서 컴포넌트를 등록하는 방법은 2가지가 있다. 전역 등록, 지역 등록이 바로 그것들이다.

     

    - 전역 컴포넌트

    <template>
      <컴포넌트 이름></컴포넌트 이름>
    </template>
    
    // 전역 컴포넌트
    Vue.component('컴포넌트 이름', {
      // 컴포넌트 내용 : template...
    });

     

    - 지역 컴포넌트 

    new Vue({
      el: '#app',
      
      // 지역 컴포넌트
      components: {
        // '컴포넌트 이름': '컴포넌트 내용'
        'app-footer': {
          template: '<footer>Footer</footer>'
        }
      }
      
      
      // 혹은, 변수에 담은 객체를 전달하는 방법도 있다.
      const anotherWay = {
        template: '<div>Another Way!</div>'
      }
      
      components: {
        'another-way': anotherWay,
      }
    });

    실제 개발환경에선 지역 컴포넌트의 방식을 대부분 등록한다. (전역방식은 플러그인이나, 전역에 사용되는 컴포넌트 등록에만 사용됨)

    통상은, 해당 인스턴스(vue 파일) 내에서 사용할 수 있는 컴포넌트들을 components 필드에 추가하여 사용하게 된다.

     

    * new Vue() 인스턴스는 <Root> 루트 컴포넌트와 1:1 관계이다.

     

     

    💚 컴포넌트 통신 방식

    컴포넌트들은 자체 격리된 고유한 데이터 유효 범위를 갖는다. 따라서, 컴포넌트 간의 데이터 통신을 위해 아래 규칙을 따른다.

    출처 : https://kr.vuejs.org/v2/guide/components.html

     

    - Props

    상위 컴포넌트에서 하위 컴포넌트로 특정 속성값을 넘겨주는 문법이다. 기본적인 바인딩 문법으로, "v-bind" 디렉티브를 사용한다.

    <template>
      <div id="app">
        <app-header v-bind:props명="상위 컴포넌트 데이터명"></app-header>
      </div>
    </template>
    
    <script>
      var appHeader = {
        template: '<h1>{{ props명 }}</h1>',
        props: ['props명'],
      }
    </script>

    템플릿 리터럴 문법( {{ 값 }} )을 통해서 data, props 등을 바인딩할 수 있으며, props 필드에 참조할 props명을 배열형태로 관리한다.

    이렇게 전달된 props는, 부모 컴포넌트의 조작을 통해 변형되면 바인딩된 자식 컴포넌트에도 전달된다. (Reactivity) 

     

    * props 검증

    다음과 같이 props에 type 검증, default 값 설정, validator 설정 등 다양한 추가동작이 가능하다.

    Vue.component('example', {
      props: {
        // 기본 타입 확인 (`null` 은 어떤 타입이든 가능하다는 뜻입니다)
        propA: Number,
        // 여러개의 가능한 타입
        propB: [String, Number],
        // 문자열이며 꼭 필요합니다
        propC: {
          type: String,
          required: true
        },
        // 숫자이며 기본 값을 가집니다
        propD: {
          type: Number,
          default: 100
        },
        // 객체/배열의 기본값은 팩토리 함수에서 반환 되어야 합니다.
        propE: {
          type: Object,
          default: function () {
            return { message: 'hello' }
          }
        },
        // 사용자 정의 유효성 검사 가능
        propF: {
          validator: function (value) {
            return value > 10
          }
        }
      }
    })

     

    * props 작명법

    html에서는 케밥 케이스(props-data), 스크립트에선 카멜 케이스(propsData)로 각각의 문법에 맞게 작성되야 올바르게 인식함

     

    - Event Emit (Event Bus)

    하위 컴포넌트에서 상위 컴포넌트로의 통신을 위해 Event Emit 문법을 활용한다. 특정 값이 아닌, 이벤트를 올려 값 수정을 유도한다.

    <template>
      <div id="app">
        <app-button v-on:이벤트명(하위 컴포넌트)="메서드명(상위 컴포넌트)"></app-button>
      </div>
    </template>
    
    <script>
      var appButton = {
        template: '<button v-on:click="passEvent">button</button>',
        methods: {
          passEvent: function() {
            this.$emit('이벤트명(하위 컴포넌트)', payload)
          }
        }
      }
    
      new Vue({
        el: '#app',
        components: {
          'app-button': appButton
        }
        methods: {
          '메서드명': function() {
            console.log('hi');
          }
        }
      })
    </script>
    1. "v-on:이벤트명" 디렉티브를 통해 특정 이벤트와 메서드를 연계할 수 있다.
    2. 먼저, 이벤트를 발생시킬 하위 컴포넌트에서 $emit Vue API를 통해 상위 컴포넌트로 이벤트명을 전달해준다.
    3. 특정 값을 넘겨주려는 경우는, $emit의 두 번째 인자부터 추가해주면 payload 필드로 값이 넘어간다.
    4. 이벤트를 받는 상위 컴포넌트에서는 하위 컴포넌트의 이벤트명과 상위 컴포넌트에서 동작할 메서드를 연결한다.

     

    - 동등 레벨 컴포넌트 간의 통신방법

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Getting Started</title>
      </head>
      <body>
        <!-- 2) Root : v-on을 통해 받은 payload 값을, 메서드를 통해 data 최신화. 이 data를 app-header의 props로 하달 -->
        <div id="app">
          <app-header v-bind:propsNum="num"></app-header>
          <app-content v-on:pass="deliverVal"></app-content>
        </div>
    
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script>
    
          // 3) app-header : props 속성으로 받음
          var appHeader = {
            template: '<div>header</div>',
            props: ['propsNum']
          }
    
          // 1) app-content : 이벤트, $emit을 통해 값 전달. payload 활용
          var appContent = {
            template: '<button v-on:click="passVal">pass</button>',
            methods: {
              passVal: function() {
                this.$emit('pass', 10);
              }
            },
          }
    
    	  // 0) Vue 인스턴스 세팅
          new Vue({
            el: '#app',
            components: {
              'app-header': appHeader,
              'app-content': appContent,
            },
            data: {
              num: 0,
            },
            methods: {
              deliverVal: function(val) {
                this.num = val
              }
            },
          })
        </script>
      </body>
    </html>
    

    확실히 React 컴포넌트의 문법이 Javascript 친화적이었다는 점을 느낀다.

    Vue만의 독특한 문법으로 작성되어야 하며, 각각의 속성(template, data, methods) 과 이를 연동하는 디렉티브가 그렇다.

     

    Vue 컴포넌트를 만들어보면서 느낀 점은, 확실히 협업에 장점이 있다고 느꼈다. (문법이 일관적이므로)

    반대로, 컴포넌트 간의 통신을 위해 Props, Event를 교환함에 따라 명명해야 할 요소가 많다.

    이 부분을 깔끔하게 해야 할 필요성을 느꼈다!!

     

    다음 글은 Vue 프로젝트에서 SPA 라우팅을 위해 사용되는 Vue Router에 대해 작성하고자 한다.

     

    [출처]

    - Vue 공식문서 : https://kr.vuejs.org/v2/guide/instance.html

    - 캡틴판교 님의 블로그 : https://joshua1988.github.io/web-development/vuejs/vuejs-tutorial-for-beginner/  

    반응형

    'Front-End(Web) > Vue' 카테고리의 다른 글

    [Vue.js] Vuex - (1) Vuex 기본  (0) 2021.06.10
    [Vue.js] Template 문법  (0) 2021.06.03
    [Vue.js] Vue Router  (0) 2021.06.02
    [Vue.js] 인스턴스 (Instance), 라이프사이클(LifeCycle)  (0) 2021.05.26
    [Vue.js] Vue 개요 및 세팅(CLI)  (0) 2021.05.10
Designed by Tistory.