티스토리 뷰

Vue

Vue - props / event emit

김관장 2022. 6. 8. 18:05

1. Vue - props?

  • 일반적인 props와 같은 의미로, 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달할 때 사용되는 단방향 데이터 전달 방식을 말합니다.

1 - 2. Vue에서 props 사용방법

   1 - 2 (1). 정적 props

<body>

     <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    
     <div id="app">
             <!-- propsdata로 'hi ~'라는 데이터 전달 -->
             <app-header propsdata="hi ~"></app-header>
     </div>

     <script>

             // 하위 컴포넌트
             let appHeader = {
                 props: ['propsdata'], //자식 컴포넌트에서 받을 props의 명칭 정의
            
                 //받은 props 데이터를 화면에 뿌려줌, props는 탬플릿 내부에서 사용 가능
                 template: '<h1>{{propsdata}}</h1>',
             }

             new Vue({
                 el: '#app',
                 components: {
                     'app-header': appHeader
                 }
             });
        
     </script>

</body>
  • app-header 컴포넌트 선언부를 보면 props라는 객체에 propsdata라는 props로 받을 명칭을 정의하고, 해당 값을 템플릿 문법( {{propsdata}} )을 통해 <h1> 태그에 사용합니다.
  • <app-header> 선언 태그 부분에서 propsdata값에 'hi ~'라는 문자열을 넘겨줍니다.
  • 실행해보면 "hi ~"라는 문자가 나오는 것을 확인할 수 있습니다.

   1 - 2 (2). 동적 props

<body>

    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    
    <div id="app">
        <!-- v-bind: 프롭스 속성이름 = "상위 컴포넌트의 데이터 이름" -->
        <app-header v-bind:propsdata="message"></app-header>
    </div>

    <script>

        let appHeader = {
            template: '<h1>{{propsdata}}</h1>',
            props: ['propsdata']
        }

        new Vue({
            el: '#app',
            components: {
                'app-header': appHeader,
            },
            data: {
                message: 'hi ~',
            }
        });
        
    </script>

</body>
  • 자식 컴포넌트에서 [ v-bind: 프롭스 속성 이름 = "상위 컴포넌트의 데이터 이름" ] 키워드를 통해 데이터를 부모 데이터를 받아 자식 컴포넌트의 props 객체를 통해 데이터를 전달받는 방식입니다.
  • <app-header> 선언 태그 부분에서 propsdata값에 "message"라는 상위 컴포넌트의 데이터 값을 넣어줬습니다. (현재 new Vue에서 정의된 데이터 객체의 message값인 "hi ~")
  • new Vue의 data객체에서 정의된 message값이 바뀔 때마다 화면에 바뀐 값으로 나오는 것을 확인 할 수 있습니다.

   1 - 2 (3). props 검증

<script>

let appHeader = {
  props: {
  
    // 기본 타입 체크 (`Null`이나 `undefinded`는 모든 타입을 허용합니다.)
    propA: Number,
    
    // 여러 타입 허용 (여기선 str, num 만 허용)
    propB: [String, Number],
    
    // 필수로 있어야 하는 값
    propC: {
      type: String,
      required: true
    },
    
    // 기본값이 있는 숫자 (여기선 100)
    propD: {
      type: Number,
      default: 100
    },
    
    // 기본값이 있는 오브젝트
    propE: {
      type: Object,
      // 오브젝트나 배열은 꼭 기본값을 반환하는 팩토리 함수의 형태로 사용되어야 합니다. 
      default: function () {
        return { message: 'hello' }
      }
    },
    
    // 커스텀 유효성 검사 함수
    propF: {
      validator: function (value) {
        // 값이 항상 아래 세 개의 문자열 중 하나여야 합니다. 
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
    
  }
}

</script>
  • 컴포넌트는 props의 유효성 검사를 위해 요구사항을 특정할 수 있습니다.
  • 타입음 다음 네이티브 생성자 중 하나를 사용할 수 있습니다.
    [ String, Number, Boolean, Function, Object, Array, Symbol ]

   1 - 2 (4). props 대소문자 구분

<body>

    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    
    <div id="app">
        <app-header v-bind:props-data="message"></app-header>
    </div>

    <script>

        let appHeader = {
            template: '<h1>{{propsData}}</h1>',
            props: ['propsData']
        }

        new Vue({
            el: '#app',
            components: {
                'app-header': appHeader,
            },
            data: {
                message: 'hi ~',
            }
        });
        
    </script>

</body>
  • HTML 어트리뷰트는 대소문자 구분이 없기 때문에 브라우저는 대문자를 소문자로 변경하여 읽습니다. 따라서 카멜 케이스(대문자와 혼용)로 props의 이름을 정한 경우 Dom 템플릿 안에서는 케밥 케이스(하이픈 - 으로 연결된 구조)를 사용해야 올바르게 동작합니다.
  • 위에서 propsData와 같이 카멜케이스로 이름을 정한 경우 v-bind:propsData가 아닌 v-bind:props-data와 같은 케밥 케이스를 사용해야 합니다.

2. Vue - event emit?

  • 이벤트 발생은 컴포넌트의 통신 방법 중 하위 컴포넌트에서 상위 컴포넌트로 통신하는 방식입니다. 
  • [ v-on:하위 컴포넌트에서 발생한 이벤트 이름="상위 컴포넌트의 메서드명" ] 키워드를 통해 이벤트를 호출할 수 있습니다.
  • this.$emit("함수명") 은 상위 컴포넌트로 올라가 v-on 으로 작성한 커스텀 이벤트를 호출합니다.

2 - 2. Vue에서 event emit 사용방법

<body>

    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    
    <div id="app">
        <p>{{num}}</p>
        <!--  v-on:하위 컴포넌트에서 발생한 이벤트 이름="상위 컴포넌트의 메서드명" -->
        <app-content v-on:addnum="addNumberFn"></app-content>
    </div>

    <script>

        let appContent = {
            //v-on:하위 컴포넌트에서 발생한 이벤트 이름="상위 컴포넌트의 메서드명"
            template: '<button v-on:click="addNumber">add</button>',
            methods: {
                addNumber: function () {
                    //상위 컴포넌트로 올라가 v-on으로 작성한 커스텀 이벤트 addnum()이 실행
                    this.$emit('addnum');
                }
            }
        }

        new Vue({
            el: '#app',
            components: {
                'app-content': appContent
            },
            methods: {
                addNumberFn: function () {
                    this.num += 1;
                }
            },
            data: {
                num: 10
            }
        })
    </script>
    
</body>
  • content 정의 시 template에서 [ v-on ~ ] 키워드로 이벤트 함수를 연결합니다.
  • 연결된 이벤트를 호출하면 content에서 정의했던 methods 객체에서 해당 이벤트를 찾아 함수를 실행합니다.
  • this.$emit('함수명') 함수를 호출하면 상위 컴포넌트인 <app-content> 태그 선언 부의 v-on으로 연결했던 이벤트를 찾아 함수를 실행합니다.
  • 그 결과 최종적으로 addNumberFn이라는 함수를 호출하고, 상위 컴포넌트인 new Vue()에서 정의했던 methods 객체에서 해당 함수를 찾아 호출합니다.
  • addNumberFn()함수를 호출하면 data.num을 하나씩 증가시켜주기 때문에 화면에 num값이 +1 씩 증가하는 모습을 확인 할 수 있습니다.

요약하자면 add 라는 버튼을 클릭하면 결과적으로 new Vue()에서 정의했던 addNumberFN() 함수를 호출하며, 그에따라 바뀐 num값을 동적으로 화면에 보여줍니다.

 

 

component와 같이 잘 숙지하자!

 

 

🔗 참고한 글

 

Vue.js

Vue.js - 프로그레시브 자바스크립트 프레임워크

kr.vuejs.org

'Vue' 카테고리의 다른 글

Vue - router  (0) 2022.06.10
Vue - method  (0) 2022.06.10
Vue - Component  (0) 2022.06.03
Vue - Instance  (0) 2022.05.30
Vue - Vue 란?  (0) 2022.05.26
댓글