[Do it! Vue.js] Vue Instance & Vue Component

728x90
반응형
SMALL

Do it! Vue.js 입문

 

Vue.js 현업 개발자이자 국내 최초 Vue.js 전문 강사의 핵심 노하우 대공개!

실무자 3일 완성! 입문자 7일 환성!

 

  • 장기효 저자
  • 이지스퍼블리싱
  • 2018.01.27

front 작업이 필요해서 급하기 스터디를 진행했다.

react 보단 vue가 러닝 커브가 낮다는 소문으로,,, 선택!

 

 


뷰 인스턴스 라이프 사이클

 

beforeCreate

인스턴스가 생성되고 나서 가장 처음으로 실행되는 단계

data 속성과 methods 속성이 아직 인스턴스에 정의되지 않고, 돔과 같은 화면 요소에도 접근할 수 없다.

 

created

data 속성과 methods 속성이 정의되었기 때문에 this.data, this.fetchData()와 같은 로직들을 이용하여 data 속성과 methods 속성에 정의된 값에 접근하여 로직을 실행할 수 있다.

 

아직 인스턴스가 화면 요소에 부착되기 전이기에 template 속성에 정의된 돔 요소로는 접근할 수 없다.

 

주로 서버에 데이터를 요청하여 받아오는 로직을 수행하기 좋다.

 

 

beforeMount

template 속성에 지정한 마크업 속성을 render() 함수로 변환한 후 el 속성에 지정한 화면 요소(돔)에 인스턴스를 부착하기 전에 호출되는 단계이다.

 

render() 함수가 호출되지 직전 로직을 추가하기에 좋다.

  • render() : 자바스크립트로 화면의 돔을 그리는 함수

 

mounted

el 속성에서 지정한 화면 요소에 인스턴스가 부착되고 나면 호출되는 단계이다.

 

template 속성에 정의한 화면 요소(돔)에 접근할 수 있어 화면 요소를 제어하는 로직을 수행하기 좋다.

 

beforeUpdate

el 속성에서 지정한 화면 요소에 인스턴스가 부착되고 나면 인스턴스에 정의한 속성들이 화면에 치환된다.

 

관찰하고 있는 데이터가 변경되면 가상 돔으로 화면을 다시 그리기 전에 호출되는 단계로, 변경 예정인 새 데이터에 접근할 수 있어 변경 예정 데이터의 값과 관련된 로직을 미리 넣을 수 있다.

 

updated

데이터가 변경되고 나서 가상 돔으로 다시 화면을 그리고 나면 실행되는 단계이다.

 

데이터 변경 후 화면 요소 제어와 관련된 로직을 추가하기 좋다.

 

데이터 값을 갱신하는 로직은 가급적이면 beforeUpdate에 추가하고, updated에서는 변경 데이터의 화면 요소(돔)와 관련된 로직을 추가하는 것이 좋다.

 

beforeDestroy

뷰 인스턴스의 데이터를 삭제하기 좋다.

 

destroyed

뷰 인스턴스에 정의한 모든 속성이 제거되고 하위에 선언한 인스턴스들 또한 모두 파괴된다.

 

Life cylcle Example

<html>
  <head>
    <title>Vue Instance Lifecycle</title>
  </head>
  <body>
    <div id="app">
      {{ message }}
    </div>
 
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
    <script>
      new Vue({
        el: '#app',
        data: {
          message: 'Hello Vue.js!'
        },
        beforeCreate: function() {
          console.log("beforeCreate");
        },
        created: function() {
          console.log("created");
        },
        mounted: function() {
          console.log("mounted");
 
 
          // 뷰 인스턴스에서 데이터 변경이 일어나게 설정해야 beforeUpdate, updated가 호출된다.
          // 데이터 변경이 없으면 updated log 찍히지 않는다.
          this.message = 'Change Hello Vue Message !';     
        },
        updated: function() {
          console.log("updated");
        }
      });
    </script>
  </body>
</html>

 

인스턴스 유효 범위

전역 컴포넌트

Vue.component('component name', {
    component contents
});

 

지역 컴포넌트

new Vue({
    components: {
        'component name': component contents
    }
});

 

<html>
  <head>
    <title>Vue Local and Global Components</title>
  </head>
  <body>
    <div id="app">
      <h3>첫 번째 인스턴스 영역</h3>
      <my-global-component></my-global-component>
      <my-local-component></my-local-component>
    </div>
 
    <hr>
 
    <div id="app2">
      <h3>두 번째 인스턴스 영역</h3>
      <my-global-component></my-global-component>
      <my-local-component></my-local-component>
    </div>
 
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
    <script>
      // 전역 컴포넌트 등록
      Vue.component('my-global-component', {
        template: '<div>전역 컴포넌트 입니다.</div>'
      });
 
      // 지역 컴포넌트 내용
      var cmp = {
        template: '<div>지역 컴포넌트 입니다.</div>'
      };
 
      new Vue({
        el: '#app',
        // 지역 컴포넌트 등록
        components: {
          'my-local-component': cmp
        }
      });
 
      // 두 번째 인스턴스
      new Vue({
        el: '#app2'
 
 
        // 여기에 components 로 my-local-component : cmp 추가하면 두 번째 인스턴스 영역에 지역 컴포넌트 추가 됨
        // components: {
        // 'my-local-component': cmp
        // }
      });
    </script>
  </body>
</html>

 

 

뷰 컴포넌트 통신

뷰의 경우 컴포넌트로 화면을 구성하므로 같은 웹 페이지라도 데이터를 공유할 수 없다.

 

컴포넌트마다 자체적으로 고유한 유효 범위(scope)를 갖기 때문이다.

 

따라서 각 컴포넌트의 유효 범위가 독립적이기 때문에 다른 컴포넌트의 값을 직접적으로 참조할 수 없다.

 

<body>
   <div id="app">
     <my-component1></my-component1>
     <my-component2></my-component2>
   </div>
 
   <script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
   <script>
     // 첫 번째 컴포넌트 내용
     var cmp1 = {
       template: '<div>첫 번째 지역 컴포넌트 : {{ cmp1Data }}</div>',
       data: function() {
         return {
           cmp1Data : 100
         }
       }
     };
 
     // 두 번째 컴포넌트 내용
     var cmp2 = {
       template: '<div>두 번째 지역 컴포넌트 : {{ cmp2Data }}</div>',
       data: function() {
         return {
            // 두 번째 컴포넌트에서 첫 번째 컴포넌트 값을 참조하려 한다. 하지만, 참조할 수 없다.
           cmp2Data : cmp1.data.cmp1Data
         }
       }
     };
 
     new Vue({
       el: '#app',
       // 지역 컴포넌트 등록
       components: {
         'my-component1': cmp1,
         'my-component2': cmp2
       }
     });
   </script>
 </body>

 

 

props

상위 컴포넌트 → 하위 컴포넌트 

// 하위
Vue.component('child-component', {
    props: ['props 속성 이름']
});
 
 
// 상위
<child-component v-bind:props 속성 이름 = "상위 컴포넌트의 data 속성"></child-component>
<div id="app">
  <child-component v-bind:propsdata="message"></child-component>
</div>
 
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
<script>
  Vue.component('child-component', {
    props: ['propsdata'],
    template: '<p>{{ propsdata }}</p>',
  });
 
  new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue! passed from Parent Component'
    }
  });
</script>
  • new Vue()로 인스턴스 생성
  • Vue.component()로 하위 컴포넌트인 child-component 등록, props 속성 추
  • <child-component> 태그 추가, propsdata 속성 이름으로 message 값을 전달

 

event 전달

하위 컴포넌트 → 상위 컴포넌트

// 하위
this.$emit('event name');
 
 
// 상위
<child-component v-on:event name="상위 컴포넌트의 메서드명"></child-component>
<div id="app">
    // event 수신
  <child-component v-on:show-log="printText"></child-component>
</div>
 
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
<script>
  Vue.component('child-component', {
    template: '<button v-on:click="showLog">show</button>',
    methods: {
      showLog: function() {
        // event 방생
        this.$emit('show-log');
      }
    }
  });
 
  new Vue({
    el: '#app',
    data: {
      message: 'Hello Vue! passed from Parent Component'
    },
    methods: {
      printText: function() {
        console.log("received an event");
      }
    }
  });
</script>
  • show 버튼을 누르면 showLog() 실행
  • showLog() 내부에서 emit으로 show-log event 발생
  • <child-component> 태그로 v-on:show-log 이벤트를 수신하고 pritText가 실행된다.
  • printText() 내부에서 console.log() 실행

 

Event Bus

상위-하위 관계가 아니여도 컴포넌트 간에 데이터를 주고받는 방법

// 이벤트 버스를 위한 인스턴스 생성
var eventBus = new Vue();
 
 
// 이벤트를 보내는 컴포넌트
methods: {
    method name: function() {
        eventBus.$emit('event name', data);
    }
}
 
 
// 이벤트를 받는 컴포넌트
methods: {
    created: function() {
        eventBus.$on('event name', function(data) {
            ...
        });
    }
}
<body>
  <div id="app">
    <child-component></child-component>
  </div>
 
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js"></script>
  <script>
    var eventBus = new Vue();
 
    Vue.component('child-component', {
      template: '<div>하위 컴포넌트 영역입니다.<button v-on:click="showLog">show</button></div>',
      methods: {
        showLog: function() {
          eventBus.$emit('triggerEventBus', 100);
        }
      }
    });
 
    var app = new Vue({
      el: '#app',
      created: function() {
        eventBus.$on('triggerEventBus', function(value){
          console.log("이벤트를 전달 받음. 전달 받은 값 : ", value);
        });
      }
    });
  </script>
</body>
  • var eventBus = new Vue() 이벤트 버스로 활용할 새 인스턴스 생성
  • Vue.component()로 child-component 생성, template, methods 속성 정의
  • show 버튼 클릭 시 showLog() 실행
  • showLog() 내부에서 eventBus.$emit()로 triggerEventBus라는 이벤트를 발생시키고 인자 값으로 100을 전달한다.
  • created 라이프 사이클 훅에 eventBus.$on()으로 이벤트를 받는 로직이 실행
  • triggerEventBus 이벤트를 수신하고 value로 100을 받아 console.log() 실행
728x90
반응형
LIST

'Study > Do it! Vue.js 입문' 카테고리의 다른 글

[Do it! Vue.js] Vue.js 란 무엇인가?  (0) 2021.02.02