개발 무지렁이

[Vue] 영역별 구성요소를 나타내는 컴포넌트와 컴포넌트 간의 관계 및 데이터 흐름 (with 컴포넌트 통신방식) 본문

Frontend/Vue

[Vue] 영역별 구성요소를 나타내는 컴포넌트와 컴포넌트 간의 관계 및 데이터 흐름 (with 컴포넌트 통신방식)

Gaejirang-e 2023. 9. 30. 20:04

𐂂 Vue 컴포넌트
화면의 영역을 구분하여, 영역별로 코드를 관리하는 구성요소를 말한다.
컴포넌트 기반으로 화면을 개발하면 🧩 재사용성이 증가한다.

𐁍 컴포넌트 간의 관계
⚠️ Vue 인스턴스를 생성하면 해당 객체는 루트(Root) 컴포넌트가 된다.
이후에 컴포넌트를 등록하는 순간 하위 컴포넌트로 위치하게 된다.
각각의 컴포넌트는 각각의 고유한 데이터 유효범위를 가지고, 각각 데이터를 관리한다.

🍟 전역 컴포넌트 Vue.component('컴포넌트태그', { 컴포넌트 내용 });
🍟 지역 컴포넌트 components: { '컴포넌트 태그', { 컴포넌트 내용 } }

📜 전역컴포넌트.html

  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
  </head>
  <body>
      <div id="app">
      <app-header></app-header> <!--컴포넌트 태그, 컴포넌트 내용 반영 -->
      <app-content></app-content>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      Vue.component('app-header', {
          template: '<h1>Header</h1>', //template, 컴포넌트가 표현되는 마크업 or 스타일
      });
      Vue.component('app-content', {
          template: '<div>Content</div>',
      });
      new Vue({
          el: '#app',
      });
    </script>  
  </body>  
  </html>

📜 지역컴포넌트.html

  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
  </head>
  <body>
    <div id="app">
      <app-footer></app-footer>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      new Vue({
          el: '#app',
        components: {
            'app-footer': {
                 template: '<footer>footer</footer>' 
            }
        }
      });
    </script>
  </body>
⚠️ 전역 컴포넌트인스턴스를 생성할 때마다, 따로 등록할 필요없이 모든 인스턴스에 등록되어있다.
⚠️ 지역 컴포넌트인스턴스마다 새로 생성해줘야한다.

𖠃 컴포넌트 통신방식


상위컴포넌트에서 하위컴포넌트로는 데이터props속성에 넣어서 내려주고
v-bind:[하위컴포넌트에서 지정한 props속성이름]="[상위컴포넌트 data 이름]"
⚠️ reactivityprops그대로 반영된다.

하위컴포넌트에서 상위컴포넌트로는 이벤트를 발생(Event emit)시켜 데이터를 조작한다.
이러한 컴포넌트 통신방식이라는 규칙이 생겼을 때, 데이터의 흐름을 추적할 수 있다.
v-on:[하위컴포넌트에서 지정한 이벤트 이름]="[상위 컴포넌트 method 이름]"

📜 데이터 내려주기.html

  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
  </head>
  <body>
      <div id="app">
      <app-header v-bind:propsdata="message"></app-header>
      <app-content v-bind:propsdata="num"></app-content>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      let appHeader = {
          template: '<h1>{{ propsdata }}</h1>',
        props: ['propsdata'],
      }

      let appContent = {
          template: '<div>{{ propsdata }}</div>',
        props: ['propsdata'],
      }

      new Vue({
          el: '#app',
        components: {
            'app-header': appHeader,
              'app-content': appContent,
        },
        data: {
               message: 'hi',
              num: 10,
        }
      });
    </script>
  </body>
  </html>  

📜 이벤트 발생시키기.html

  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
  </head>
  <body>
    <div id="app">
      <p>{{ num }}</p>
      <app-header v-on:pass="logText"></app-header>
      <app-content v-on:increase="increaseNumber"></app-content>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      let appHeader = {
          template: '<button v-on:click="passEvent">click me</button>',
        methods: {
            passEvent: function() {
                this.$emit('pass');  
            }
        }
      }

      let appContent = {
          template: '<button v-on:click="addNumber">add</button>',
        methods : {
            addNumber: function() {
                this.$emit('increase') 
            }
        }
      }

      new Vue({
          el: '#app',
        components: {
            'app-header': appHeader,
              'app-content': appContent,
        },
        methods: {
            logText: function() {
                console.log('hi'); 
            },
              increaseNumber: function() {
                this.num += 1; 
            }
        },
        data: {
            num: 10 
        }
      });
    </script>
  </body>
  </html>
Comments