DEV Community

Cover image for Vue.js 3 이벤트 뻐-스
Composite
Composite

Posted on

Vue.js 3 이벤트 뻐-스

내가 살다살다 이딴 포스트 하나 쓰려고 포토샵까지 꺼내들게 하다니...

SI 아니랄까봐 2022년 Vue 에서 밀고있는 Pinia 도 안쓰고
아 그래 너무 최신 기술이라 거부감 느낀다 쳐.
아니, 하다못해 오랫동안 SI에서 잘만 쓰고 있는 Vuex조차도 안 쓰고...
뭐? 이벤트 버스???

Vue 3 에다가 이벤트 버스???

징-하다.

그래... 그래서 만들었다.
Composition API 시대에 예전 new Vue() 못 쓰니...
하지만 ref()reactive() 사용법을 알면 그리 어렵지 않게 만들 수 있다.
그리고 이걸 전역으로 돌아가도록 하는 게 핵심 포인트.

자, 여기 코드가 있다.
코멘트 주우 늘어진 건 너희들 자동완성하기 좋으라고 해준 거니 감사히 여겨라.

좋아. 원리를 설명해주지.

초기화는 그저 컴포넌트 스크립트 setup() 함수 및 <script setup> 태그 내용 안에서 준비한 함수 useEventBus() 만 호출하여 상수에 담으면 준비 끝!

on

이벤트명이 키인 객체가 메인이다. 그리고 그 속성들은 이렇다.
당연하겠지만 콜백은 여러개 있을 수 있으니, 이를 배열로 담아둔다.
그리고 trigger 속성에 이벤트 발생 시 속성을 변경하여 반응형을 유도하기 위해 ref 함수를 사용한다.
그리고 이 trigger 속성에 대한 변경을 감지할 watch 함수를 정의하여, 이를 stopper 에 정의하는데, 왜 stopper를 정의하냐면, watch 함수를 호출하면 반환하는 값이 이 watch 작업을 중지하기 위해 호출할 수 있는 함수를 반환하기 때문이다. 이에 대해 다음 메소드에 후술하겠다.

emit

이벤트 리스너를 만들었으면, 이제 발생을 시켜야겠지? emit 메소드를 통해 이벤트를 발생시키도록 유도하면, 이벤트명 키를 찾아 이 안에 있는 trigger 속성에 있는 ref 객체의 값을 변경시켜 반응을 유도한다, 객체 값을 변경시키면, watch 함수 콜백이 발동하는데, 변경한 값을 인자로 받아 배열 내에 있는 모든 콜백을 호출하게 된다.
그렇게 되면 같은 이벤트명을 A.vue에 정의해도, B.vue에 정의하면 모두 호출하게 된다.

off

하지만 이벤트를 추가했으면 삭제도 필요하겠지?
이런 상황을 위해 준비한 게 바로 off 메소드다.
뭐 별거 없다. 이벤트명과 함수명 넣으면 이벤트 안에 함수 날라가고,
함수 없이 이벤트명만 넣으면 이벤트 콜백은 다 사라지게 된다.
이 때, 이벤트 콜백이 사라질 때가 바로 핵심인데,
이벤트 콜백이 사라질 때도 watch 함수가 동작하는 것은 낭비다.
따라서 준비해둔 stopper 속성에 담긴 해제 함수를 호출하여 정리하는 것이다.
간단하지?

해결해야 할 것들.

안타깝지만 완벽한 구현체는 아니다. 내가 깜박한 점도 있지만, 이들을 해결해야 한다.

  • 이벤트 버스를 사용한 특정 컴포넌트가 해체될 때(Destroy) 해당 컴포넌트에 등록한 리스너도 사라져야 하는 부분이 구현되지 않았다. 구현 안 하면 좀비 콜백이 되어 잠재적인 스크립트 오류를 유발하고 배열이 쌓이게 되면 좋을 게 없지 않은가.
  • 그냥 Vue 에서 공식으로 넣어준 Provider/Inject 쓰면 안되겠니?

이 외에도 내가 모르는 잠재적인 문제가 내재되어 있는데,
이들의 해결은 여러분에게 맡긴다.
어딜 날로 쳐먹으려고...

아 미안, 조만간 재대로 된 이벤트 버스 구현체 만들게 되면 그때 Github 에 풀게. 언제가 될 지는 모르겠지만 어자피 Vue 코딩 업무 보게 될 수 있으니 그때를 기약하도록 하자. 아니면 뭐 Stack Overflow 가서 찾아도 되고, 그냥...

GitHub logo developit / mitt

🥊 Tiny 200 byte functional event emitter / pubsub.

mitt
npm build status gzip size

Mitt

Tiny 200b functional event emitter / pubsub.

  • Microscopic: weighs less than 200 bytes gzipped
  • Useful: a wildcard "*" event type listens to all events
  • Familiar: same names & ideas as Node's EventEmitter
  • Functional: methods don't rely on this
  • Great Name: somehow mitt wasn't taken

Mitt was made for the browser, but works in any JavaScript runtime. It has no dependencies and supports IE9+.

Table of Contents

Install

This project uses node and npm. Go check them out if you don't have them locally installed.

$ npm install --save mitt
Enter fullscreen mode Exit fullscreen mode

Then with a module bundler like rollup or webpack, use as you would anything else:

// using ES6 modules
import mitt from 'mitt'
// using CommonJS modules
var mitt = require('mitt')
Enter fullscreen mode Exit fullscreen mode

The UMD build is also available on unpkg:

<script src="https://unpkg.com/mitt/dist/mitt.umd.js">
Enter fullscreen mode Exit fullscreen mode

이거 쓰든가.

끗.

Top comments (0)