[Vue.js] mitt (Vue3에서 컴포넌트간 통신방법)

2021. 7. 4. 20:54프론트엔드/Vue.js

728x90

 

 

[에러내용] Vue3에서 EventBus를 적용해보려 했는데, 계속 $on관련 에러발생

 


 

Vue3마이그레션(사용)을 위해 알아둘 점

Vue3에서는 $on, $once, $off를 사용하지 않음

$emit은 parent componet에 부착되어 trigger event handler API로 여전히 사용됨

'EventBus'는 Vue가 추천하는 공식적인 방법이 아님

'mitt'이라는 외부라이브러리를 이용하여 EventBus구현

 

mitt

외부 라이브러리

mitt라이브러리는 커스텀이벤트를 만들어 송출, 수신할 수 있게 해줌

기존의 eventBus 대체하여 사용 가능

 


mitt사용예시

나의 경우,  'TodoInput.vue'에서 todoInput이라는 입력값을 입력받고 형제컴포넌트인 'TodoList.vue'로 넘겨서 dynamicLists로 todoInput값을 추가시키는 것이 목적

<template>
<div>
  <TodoInput></TodoInput>
  <TodoList></TodoList>
</div>
</template>

<script>
 import TodoInput from './components/TodoInput.vue';
 import TodoList from './components/TodoList.vue';

export default { 
  name: 'App',
  components: {
    TodoInput
    ,TodoList
  }
}
</script>

<style>
</style>

 

 

1. mitt 설치(mitt은 외부라이브러리이므로 별도 설치필요)

>npm install --save mitt

 

2. main.js(다른 js파일 작성해도 무관) emitter등록

Vue의 globalProperties로 emitter를 등록

import { createApp } from 'vue'
import App from './App.vue'
import mitt from 'mitt'

const emitter = mitt();
const app = createApp(App);
app.config.globalProperties.emitter = emitter
app.mount('#app')

//이렇게 사용불가
// const emitter = mitt();
// createApp(App).config.globalProperties.emitter = emitter
// createApp(App).mount('#app')

 

3. 이벤트 보내기 

<script>
export default{
  methods:{
  	enterKeyFunction(){
    	this.emitter.emit('addTodoInput', this.todoInput)
    	this.todoInput = '';
    }
  }
}
</script>

 

TodoInput.vue 전체소스

<!-- 할 일 입력 -->
<template>
    <div class="todoapp">
      <h1>TODOS</h1>
      <input
        id="new-todo-title"
        class="new-todo"
        placeholder="할일을 추가해주세요"
        autofocus
        @keyup.enter="enterKeyFunction"
        v-model="todoInput"
      />
    </div>
</template>

<script>
export default {
    data(){
        return{
            todoInput :'',
        }
    },
    methods:{
        enterKeyFunction(){
            this.emitter.emit('addTodoInput', this.todoInput)
            this.todoInput = '';
        }
    }
}
</script>

 

4. 이벤트 받기

<script>
export default{
    mounted(){
        this.emitter.on('addTodoInput',this.addTodoInputFunction)
    },
}
</script>

 

TodoList.vue 전체소스

<template>
   <div class="todoapp">
      <ul id="todo-list" class="todo-list" v-if="showTodoList"> 
          <li v-for="(list, index) in dynamicLists[0]" :key="index">
            <div class="view">
            <label class="label">{{list.item}}</label>
            </div>
            <input class="edit" value="새로운 타이틀" />
        </li>
      </ul>
    </div>
</template>

<script>
export default {
    data(){
        return {
            dynamicLists:[{}],
            now:"0000년00월00일00시00분00초", //입력시간세팅
        }
    },
    created(){
        let totCnt = 0;
        this.localStorageLength = localStorage.length
        for(let i=0; i<this.localStorageLength; i++){
            if(localStorage.key(i).indexOf('loglevel:') === -1){
             this.dynamicLists[0][localStorage.key(i)] = JSON.parse(localStorage.getItem(localStorage.key(i)));
             if( this.dynamicLists[0][localStorage.key(i)].completed){
                 this.isCompletedArr[localStorage.key(i)] = true;
             }
             totCnt++;
            }
        }
        this.totalCount = totCnt;
    },
    mounted(){
        this.emitter.on('addTodoInput',this.addTodoInputFunction)
    },
    methods:{
        getCurrTime(){
         let date = new Date();
         this.now = `${date.getFullYear()}년 ${date.getMonth()+1}월 ${date.getDate()}일 ${date.getHours()}시 ${date.getMinutes()}분 ${date.getSeconds()}초 `;
        },
        addTodoInputFunction(todoInput){
            this.getCurrTime();
            if(todoInput.trim()!=="" && !localStorage.getItem(todoInput) ){
            let value ={
                        item:todoInput
                        ,completed:false
                        ,time:this.now
            };
             localStorage.setItem(todoInput,JSON.stringify(value));
             this.dynamicLists[0][todoInput] = JSON.parse(localStorage.getItem(todoInput));
            }
        },
  }
  </script>

 

728x90