[Vue] Vue시작 (6) - event, props

권준혁·2020년 12월 6일
0

vue

목록 보기
6/8
post-thumbnail

props를 이용해서 상위컴포넌트에서 하위컴포넌트에 데이터를 전달하고, event를 통해 하위컴포넌트에서 상위컴포넌트로 전달하는 것은
React와 동일하다.

Vue에서는 props를 어떻게 전달하는지 알아보자

  <body>
    <template id="listTemplate">
      <li>{{message}}</li>
    </template>
    <script>
      Vue.component("list-component", {
        template: "#listTemplate",
        props: ["message","count"],
      });
    </script>
    <div id="app">
      <ul>
        <list-component message="Hello"></list-component>
        <list-component message="씬짜오"></list-component>
        <list-component message="니하오마"></list-component>
        <list-component count="21"></list-component>
      </ul>
    </div>
  </body>
  <script>
    Vue.config.devtool = true;
    const vm = new Vue({
      el: "#app",
    });
  </script>

props속성에 배열을 이용해 props명을 전달한다.
주의할 점이 있다면 컴포넌트 작성시 속성명을 부여할 때 카멜케이스를 사용했다면 태그에서 속성명을 사용할 땐 케밥케이스를 사용해야 한다는 것이다.
myProps라는 이름으로 전달을 했을 때, my-props로 사용한다.

React에서 HTML5의 dataset을 사용할 때 data-my-props는 dataset.myProps로 사용했던 것과 같다.
HTML이 대소문자 구분을 안하기 때문이다.

속성을 객체로 사용하기

속성명을 배열 형태로 간단하게 전달할 수도 있지만, 엄격한 유효성 검증이 필요하다면 객체형태로 사용할 수 있다.

  <body>
    <template id="listTemplate">
      <li>{{message}}</li>
    </template>
    <script>
      Vue.component("list-component", {
        template: "#listTemplate",
        props: {
      	 message: { type:String, default:"안녕하세요"},
         count: { type:Number, required: true },
      });
    </script>
    <div id="app">
      <ul>
        <list-component message="Hello"></list-component>
        <list-component message="씬짜오"></list-component>
        <list-component message="니하오마"></list-component>
      </ul>
    </div>
  </body>
  <script>
    Vue.config.devtool = true;
    const vm = new Vue({
      el: "#app",
    });
  </script>

직관적이기 때문에 쉽게 용도를 알 수 있다. 기본값과 필수값을 설정하고있다.

Vue개발자도구를 열어보면
list-components 컴포넌트에서는 {{}}를 이용해서 표현하고 있어 number로 타입을 정했지만 문자열로 출력된다.

이 문제는 v-bind디렉티브를 이용하면 해결된다. :count 를 이용해서 속성을 전달해보면 해결된다.

...
<list-component message="신짜오" :count="21" />

data는 함수로 정의해야한다. 객체로 정의하면 재사용시에 동일한 객체를 참조하기 때문에 문제가 발생한다. 함수로 정의해 객체를 리턴하게 만들어야 매번 새로운 객체를 생성하기 때문에 재사용 시마다 각각 상태값을 사용할 수 있다.

props의 default에서도 마찬가지다 배열이나 객체를 전달 할 때 default를 부여하려면 반드시 함수를 이용해야 한다.

props를 전달받고나면 String으로 변경되어있는 문제는 디렉티브를 사용해 String으로 전달(리터럴이 자바스크립트로 인식되지 않아서)되지 않도록하자. 일반적으로 변수에 담아서 디렉티브를 통해 전달하므로 문제가 안된다.

이벤트 전달하기

  <body>
    <!-- 자식 컴포넌트 -->
    <template id="childTemplate">
      <div>
        <button v-on:click="clickEvent" v-bind:data-lang="buttonInfo.value">
          {{ buttonInfo.text }}
        </button>
      </div>
    </template>
    <script>
      Vue.component("child-component", {
        template: "#childTemplate",
        props: ["buttonInfo"],
        methods: {
          clickEvent: function (e) {
            this.$emit("timeclick", e.target.innerText, e.target.dataset.lang);
          },
        },
      });
    </script>

    <!-- 부모 컴포넌트 -->
    <template id="parent-template">
      <div>
        <child-component
          v-for="s in buttons"
          v-bind:button-info="s"
          @timeclick="timeclickEvent"
        >
        </child-component>
        <hr />
        <div>{{ msg }}</div>
      </div>
    </template>
    <script>
      Vue.component("parent-component", {
        template: "#parent-template",
        props: ["buttons"],
        data: function () {
          return { msg: "" };
        },
        methods: {
          timeclickEvent: function (k, v) {
            this.msg = k + ", " + v;
          },
        },
      });
    </script>
    <div id="app">
      <parent-component :buttons="buttons"></parent-component>
    </div>
    <script>
      const rootVue = new Vue({
        el: "#app",
        data: {
          buttons: [
            { text: "Hello", value: "영어" },
            { text: "안녕", value: "한국어" },
            { text: "씬짜오", value: "베트남어" },
            { text: "니하오", value: "중국어" },
          ],
        },
      });
    </script>
  </body>

React와는 다르게 props를 전달할 때 명시적으로 이벤트임을 알려줘야 하는 것을 주의하자.


profile
웹 프론트엔드, RN앱 개발자입니다.

0개의 댓글