tech.junha.kr

노트/Vue.js

2장 인스턴스와 컴포넌트

작성

2장. 화면 개발의 필수 단위

  1. 인스턴스: 레고를 조립하는 기본 판
  2. 컴포넌트: 레고 블록

1) 인스턴스

  • 화면 개발을 위해 필수적으로 생성하는 기본 단위

(1) 뷰 인스턴스 정의와 속성

new Vue({
  el: '#app',
  data: {
    message:'value from data'
  }
})
  • new Vue(): 뷰 인스턴스 생성자
  • 뷰 인스턴스의 정의된 프로퍼티
    1. el: 뷰로 만든 화면이 그려지는 시작점을 나타내는 돔 요소
    2. template: 마크업 요소 정의
    3. methods: 이벤트, 화면 동작과 같은 화면 로직을 제어하는 메서드 정의
    4. created: 인스턴스가 생성되자마자 실행할 로직 정의
    5. data: 바인딩할 데이터 key:value형식으로 정의

(2) 뷰 인스턴스의 유효 범위

  • 인스턴스의 유효 범위: 뷰 인스턴스를 생성하면 HTML 특정 범위 안에서만 옵션 속성들이 나타난다.
new Vue({
  el:'#app',
})
<div id="app">
<!-- Vue 인스턴스의 유효범위 -->
</div>

(3) 뷰 인스턴스 라이프 사이클

1. beforeCreate
  • data, methods 속성이 인스턴스에 정의되어 있지 않고 돔과 같은 화면 요소에도 접근할 수 없다.
2. created
  • data, methods 속성 접근하여, 로직 실행 가능
  • 인스턴스가 화면에 부착되기 전이기 때문에, template 속성에 정의된 돔 요소에 접근할 수 없다.
3, beforeMount
  • 인스턴스르 부착하기 전에 호출되는 단계이다.
  • render() 함수가 호출되기 직전의 로직을 추가하기 좋다.
4. mounted
  • template 속성에 정의한 화면 요소에 접근 할 수 있어 화면 요소 제어하는 로직 수행하는 단계이다.
  • 돔에 인스턴스가 부착되자마자 바로 호출되기 때문에 하위 컴포넌트나 외부 라이브러리에 의해 추가된 하면 요소들이 최종 HTML 코드로 변환되는 시점과 다를 수 있다.
5. beforeUpdate
  • 데이터 관찰: 뷰의 반응성을 제공하기 위해 $watch 속성으로 감시한다.
  • 데이터가 변경되면 가상 돔으로 화면을 다시 그리기 전에 호출되는 단계이다.
  • 변경 예정인 데이터에 접근할 수 있어, 관련 로직을 미리 넣을 수 있다.
6. updated
  • 데이터가 변경되고 나서 가상 돔으로 다시 화면을 그리고 나서 실행되는 단계이다.
  • 데이터 변경으로 인한 화면 요소 변경까지 완료된 시점이므로, 데이터 변경 후 화면 요소 제어와 관련된 로직을 추가하기 좋은 단계이다.
7. beforeDestroy
  • 뷰 인스턴스가 뷰 인스턴스가 없어지기 직전에 호출되는 단계, 아직 인스턴스에 접근할 수 있어 인스턴스의 데이터를 삭제하기 좋은 단계다.
8. destroyed
  • 뷰 인스턴스에 정의한 모든 속성이 제거되고 하위에 선언한 인스턴스들 모두 파괴된다.
new Vue({
  el:'#app',
  data:{
    message:'Hello'
  },
  beforeCreate(){

  },
  created(){

  },
  mounted(){
    this.message = 'changed'
  },
  updated(){
    console.log('updated')
  }
})

2) 컴포넌트

  • 컴포넌트는 블록이다. 조합하여 화면을 구조화하여 일괄적인 패턴으로 구성할 수 있다.

(1) 전역 컴포넌트

Vue.component('global-component',{
  template:'<div>전역 컴포넌트<div>'
});
  1. Vue.component():뷰 생성자 컴포넌트 등록
  2. 인스턴스 객체 생성
  3. 특정 화면 요소에 인스턴스 부착
  4. 인스턴스 내용 반환: <component> => <div>

(2) 지역 컴포넌트

  • 지역 컴포넌트는 인스턴스 유효 범위를 따른다.
new Vue({
  el:'#app',
  components:{
    'local-component': {
      template:'<div>지역 컴포넌트</div>'
    }
  }
})
  • 지역 컴포넌트는 해당 el의 특정 범위 안에서만 컴포넌트가 유효하다.
<div id='app1'>
  <global-component></global-component>
  <local-component></local-component>
</div>
// 전역 컴포넌트
// 지역 컴포넌트

<div id='app2'>
  <global-component></global-component>
  <local-component></local-component>
</div>
<script>
// 전역 컴포넌트

Vue.component('global-component',{
  template:'<div>전역 컴포넌트<div>'
});

new Vue({
  el:'#app1',
  components:{
    'local-component': {
      template:'<div>지역 컴포넌트</div>'
    }
  }
})

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

3) 뷰 컴포넌트 통신

  • 컴포넌트는 유효 범위가 독립적이기 때문에 다른 컴포넌트의 값을 직접적으로 참조할 수 없다.
  • 따라서 뷰에서 정의한 상위 => 하위 컴포넌트 데이터 전달 방법을 따라야 한다.
  • 상위 컴포넌트에서는 props전달을, 하위 컴포넌트에서는 이벤트 발생을 전달한다.

(1) props: 상위에서 하위 컴포넌트로 데이터 전달하기

Vue.component('child-component',{
  props: ['propsdata']
})
<child-component v-bind:props propsdata="상위 컴포넌트의 데이터"></child-component>
  • 사용 예시
<div id="app">
  <child-component v-bind:propsdata="message"></child-component>
</div>

<script>
  Vue.component('child-component',{
    props:['propsdata'],
    template:'<p>{{propsdata}}</p>'
  })

  new Vue({
    el: '#app',
    data:{
      message:"psssed from Parent Component"
    }
  })
</script>
  • 뷰 인스턴스 자체가 상위 컴포넌트가 되어, 새로 등록된 컴포넌트는 자식 컴포넌트가 된다.

(2) $emit(): 하위에서 상위 컴포넌트로 이벤트 전달하기

  • 하위 컴포넌트는 이벤트 발생을 통해 상위 컴포넌트와 통신한다.
  1. 이벤트 발생: $emit()
  2. 이벤트 수신: v-on:
 // 이벤트 발생
this.$emit('이벤트명')
// 이벤트
<child-com v-on:이벤트명="상위 컴포넌트 메서드명"></child-com> 
  • 사용 예시
<child-com v-on:show-log="printLog"></child-com>
<!-- `show-log` 이벤트 수신 후 상위 컴포넌트 메서드 이용 -->

<script>
  Vue.component('child-com',{
    template:'<button v-on:click="showLog">show</button>',
    methods:{
      showLog() {
        this.$emit('show-log') // 'show-log' 이벤트 발생
      }
    }
  })

  new Vue({
    el:'#app',
    methods:{
      printLog(){
        console.log('parent 컴포넌트 실행')
      }
    }
  })
</script>
  1. this.$emit('이벤트') in 하위 컴포넌트의 메서드
  2. v-on:이벤트="상위 컴포넌트 메서드" in 하위 컴포넌트 등록 태그

(3) 같은 레벨의 컴포넌트 간 통신

  • 상위에서 하위로만 데이터를 전달해야 하는 통신 규칙을 따르기 때문에 옆 컴포넌트에 값을 전달하려면, 하위에서 공통 상위 컴포넌트로 이벤트를 전달한 후 공통 상위 컴포넌트에서 2개의 하위 컴포넌트에 props을 내려 보내야 한다.
  • 하지만 이런 통신 구조는 상위 컴포넌트가 필요 없음에도 불구하고 같은 레벨을 통신하기 위해 강제로 상위 컴포넌트를 두어야 한다.

(4) 이벤트 버스: 관계 없는 컴포넌트 간 통신

  • 상, 하위 관계를 유지하고 있지 않아도 컴포넌트간 데이터를 전달할 수 있다.
  • 이벤트 버스를 위한 추가 인스턴스를 생성한다.
<div id="sibling1"></div>
<div id="sibling2"></div>

<script>
    var eventBus = new Vue();

      new Vue({
        el: '#sibling1',
        template: '<button v-on:click="showLog">버튼</button>',
        methods: {
          showLog() {
            eventBus.$emit('triggerEventBus', 100);
          },
        },
      });

      new Vue({
        el: '#sibling2',
        created() {
          eventBus.$on('triggerEventBus', (value) => console.log(value));
        },
      });

</script>
  • 컴포넌트가 많아지면 어디서 어디로 보냈는지 관리하기 힘들기 때문에 이는 뷰엑스 상태관리 도구를 통해 해결해야 한다.