본문 바로가기
WEB/Vue.js

[Vue] Vue Component

by 댕꼬 2022. 5. 10.
728x90

Vue Component


 컴포넌트(Component)

  • Vue의 가장 강력한 기능 중 하나
  • HTML Element를 확장하여 재사용 가능한 코드를 캡슐화
  • Vue Component는 Vue Instance이기도 하기 때문에 모든 옵션 객체를 사용
  • Life Cycle Hook 사용가능
  • 전역컴포넌트와 지역컴포넌트 존재

 

전역컴포넌트 등록

<body>
  <div id="app1">
    <my-global></my-global> <!-- 얘는 Myglobal안되고 , 케밥표기법만 가능-->
  </div>
  <div id="app2">
    <my-global></my-global>

  </div>
  <script>
    // 전역 컴포넌트 설정 -> app1, app2 모두적용
    Vue.component("MyGlobal", {
      template: `<h2>전역컴포넌트입니다</h2>`
    })
    
    new Vue({
      el: '#app1',
    });
    new Vue({
      el: '#app2',
    });
  </script>
</body>

** 케밥표기법 : 케밥이 꽂혀있는것처럼 -를 이용하여 이름을 표기, 전부 소문자

 

코드실행화면

지역컴포넌트 등록

<body>
  <div id="app1">
    <my-local></my-local>
  </div>
  <div id="app2">
    <my-local></my-local> <!--적용안됨-->
  </div>
  <script>
    new Vue({
      el: '#app1',
      // 지역 컴포넌트 설정-> app1만적용
      components: {
        MyLocal: {
          template: `<h2>지역컴포넌트입니다</h2>`
        }
      }

    });
    new Vue({
      el: '#app2',
    });
  </script>
</body>

코드실행화면

Component Template

<body>
  <div id="app">
    <my-comp></my-comp>
  </div>
  <!-- template 설정 -->
  <!-- 실제로 있는건 아니고 여기서 화면 만들어서 app에 뿌림-->
  <template id="mycomp">
    <div>
      <h2>{{msg}}</h2>	<!--data 사용가능-->
    </div>
  </template>
  <script>
    Vue.component('MyComp', {
      template: '#mycomp',	//아이디로 알려줌->7행
      data() {    //component에서 data는 함수형식으로만 사용 가능
        return {
          msg: 'hello component',
        };
      },
    });

    new Vue({
      el: '#app',
    });
  </script>
</body>

코드실행화면

Component Data 공유

전역변수와 지역변수에 따른 Data공유

 

- count 가 전역일 경우

<body>
  <h2>컴포넌트 데이터 공유 문제</h2>
  <div id="app">
    <count-view></count-view>
    <count-view></count-view>
    <count-view></count-view>
  </div>
  <template id="CountView">
    <div>
      <span>{{ count }}</span>
      <button @click="count++">클릭</button>
    </div>
  </template>
  <script>
    let num = {
      count: 0,
    };
    Vue.component('countView', {
      data() {
        return num;
      },
      template: '#CountView',
    });
    new Vue({
      el: '#app',
    });
  </script>
</body>

어느 곳을 눌러도 다 같이 증가

- count 가 지역일 경우

<body>
    <h2>컴포넌트 데이터 공유 문제 해결</h2>
    <div id="app">
      <count-view></count-view>
      <count-view></count-view>
      <count-view></count-view>
    </div>
    <template id="CountView">
      <div>
        <span>{{ count }}</span>
        <button @click="count++">클릭</button>
      </div>
    </template>
    <script>
      Vue.component('CountView', {
        template: '#CountView',
        data() {
          return {
            count: 0,
          };
        },
      });
      new Vue({
        el: '#app',
      });
    </script>
  </body>

각 버튼마다 카운트가 증가하는 모습

 

컴포넌트간 통신

  • 상위(부모) - 하위(자식)컴포넌트 간의 data전달 방법
  • 부모->자식 : props라는 속성 전달
  • 자식->부모 : emit event로만 전달 가능

 

상위에서 하위 컴포넌트로 data전달

<body>
  <div id="app">
    <h2>props test</h2>
    <input type="text" v-model="msg" />
    <child-component :pdata="msg"></child-component> 
  </div>
  <script>
    //하위 컴포넌트
    Vue.component("ChildComponent", {
      template: `<span>{{pdata}}</span>`,
      props: {  
        pdata: {
          type: String,
          required: true,
        }
      }
    })
    new Vue({
      el: '#app',
      data() {
        return {
          msg: "",
        }
      },
    });
  </script>
</body>

props를 이용한 데이터 전달

객체의 속성(properties) 전달 props

- 오브젝트의 모든 속성을 전달할 경우, v-bind:prop-name대신 v-bind만 작성함으로써 모든 속성 props로 전달 가능

body>
  <h2>컴포넌트 객체 데이터 전달</h2>
  <div id="app">
    <member-view v-bind:member="user"></member-view>
  </div>
  <template id="MemberView">
    <div>
      <div>이름 : {{ member.name }}</div>
      <div>나이 : {{ member.age }}</div>
      <div>이메일 : {{ member.email }}</div>
    </div>
  </template>
  <script>
    Vue.component('memberView', {
      props: ['member'],
      template: '#MemberView',
    });
    new Vue({
      el: '#app',
      data() {
        return {
          user: {
            name: '홍길동',
            age: 22,
            email: 'hong@ssafy.com',
          },
        };
      },
    });
  </script>
</body>

 

사용자 정의 이벤트(Custom event)

- 이벤트 이름은 컴포넌트 및 props와 달리 자동 대소문자 변환을 제공하지 않는다.

- 대소문자를 혼용하는 대신 emit할 정확한 이벤트 이름을 작성하는 것을 권장

- v-on이벤트 리스너는 항상 자동으로 소문자 변환

- 이벤트 이름은 케밥표기법을 사용할 것을 권장

 

하위에서 상위 컴포넌트로 event 전달

: 하위에 있는 버튼을 누르면 count 데이터가 상위에 컴포넌트에 전달

<body>
  <div id="app">
    <h4>당신이 좋아하는 파트를 선택하세요</h4>
    <h2>총 투표수 : {{ total }}</h2>
    <subject v-on:add-total-count="addTotalCount" title="코딩"></subject>
    <subject v-on:add-total-count="addTotalCount" title="알고리즘"></subject>
  </div>
  <script>
    Vue.component('Subject', {
      template: '<button v-on:click="addCount">{{title}} - {{ count }}</button>',
      //props 설정
      props: ["title"],
      data: function () {
        return {
          count: 0,
        };
      },
      methods: {
        addCount: function () {
          this.count += 1;
          // 부모 v-on:이름 에 해당하는 이름의 이벤트를 호출
          this.$emit("add-total-count", "aaa");

        },
      },
    });

    new Vue({
      el: '#app',
      data: {
        total: 0,
      },
      methods: {
        addTotalCount: function () {
          this.total += 1;
        },
      },
    });
  </script>
</body>

코딩count 2 와 알고리즘count 5가 전달되고 있다.

 

728x90

'WEB > Vue.js' 카테고리의 다른 글

[Vue] Axios  (0) 2022.05.11
[Vue] Vue event  (0) 2022.05.10
[Vue] Vue Instance  (0) 2022.05.10
[Vue] Vue Directive  (0) 2022.05.04
[Vue] Vue.js란  (0) 2022.05.03

댓글