이벤트 처리(Event Handling)

이벤트 처리(Event Handling)

사용자가 버튼을 누르고, 폼을 제출하고, 키를 입력하는 순간마다 앱은 반응해야 해요. Vue에서는 v-on 디렉티브(보통 @로 줄여 씀)로 DOM 이벤트를 듣고, 트리거되면 JavaScript를 실행하게 해요. 이벤트 리스너, 인라인·메서드 핸들러, 그리고 각종 수식어를 정리할게요.

출처: https://vuejs.org/guide/essentials/event-handling.html

이벤트 듣기

사용법은 v-on:click="handler" 또는 축약형 @click="handler"예요. 핸들러 값은 두 종류가 있어요.

  1. 인라인 핸들러 — 이벤트가 트리거될 때 실행될 인라인 JavaScript (네이티브 onclick 속성과 유사).
  2. 메서드 핸들러 — 컴포넌트에 정의된 메서드를 가리키는 속성 이름이나 경로.
<button @click="count++">Add 1</button>
<p>Count is: {{ count }}</p>

로직이 복잡하면 메서드 핸들러를 써요.

function greet(event) {
  alert(`Hello ${name.value}!`)
  // event 는 네이티브 DOM 이벤트
  if (event) {
    alert(event.target.tagName)
  }
}
<button @click="greet">Greet</button>

메서드 핸들러는 자동으로 트리거한 네이티브 DOM 이벤트 객체를 받아요. 템플릿 컴파일러는 v-on 값이 유효한 JavaScript 식별자나 속성 접근 경로인지 확인해서 메서드 핸들러인지 인라인 핸들러인지 판별해요. foo, foo.bar, foo['bar']는 메서드 핸들러로, foo()count++는 인라인 핸들러로 처리돼요.

인라인 핸들러에서 메서드 호출·이벤트 인자

인라인 핸들러에서 메서드를 호출하면 네이티브 이벤트 대신 커스텀 인자를 전달할 수 있어요.

<button @click="say('hello')">Say hello</button>

원본 DOM 이벤트가 필요하면 특별 변수 $event로 넘기거나 인라인 화살표 함수를 써요.

<button @click="warn('Form cannot be submitted yet.', $event)">Submit</button>
<button @click="(event) => warn('Form cannot be submitted yet.', event)">Submit</button>

이벤트 수식어(event.preventDefault() etc.)

핸들러 안에서 event.preventDefault()event.stopPropagation()을 호출하는 일은 흔한데, 그보다는 메서드가 DOM 이벤트 세부 사항 대신 데이터 로직에만 집중하게 하는 게 좋아요. 그래서 Vue는 v-on용 이벤트 수식어를 제공해요.

  • .stop
  • .prevent
  • .self
  • .capture
  • .once
  • .passive
<!-- 클릭 이벤트 전파 중단 -->
<a @click.stop="doThis"></a>

<!-- submit 이벤트가 페이지를 더 이상 리로드하지 않음 -->
<form @submit.prevent="onSubmit"></form>

<!-- 수식어 체이닝 가능 -->
<a @click.stop.prevent="doThat"></a>

<!-- 수식어만 -->
<form @submit.prevent></form>

<!-- event.target 이 요소 자신일 때만 핸들러 트리거 (자식 요소가 아님) -->
<div @click.self="doThat">...</div>

수식어를 쓸 때는 순서가 중요해요. @click.prevent.self는 요소 자신과 자식의 기본 동작을 모두 막고, @click.self.prevent는 요소 자신의 기본 동작만 막아요. .capture, .once, .passive는 네이티브 addEventListener의 옵션을 반영해요. .passive는 모바일 터치 리스너 성능 개선에 주로 쓰여요. .passive.prevent를 함께 쓰면 안 돼요.

키 수식어(Key Modifiers)

키보드 이벤트를 들을 때 특정 키를 확인해야 할 때가 많아요. Vue는 키 이벤트에 키 수식어를 추가할 수 있어요.

<!-- `key` 가 Enter 일 때만 submit 호출 -->
<input @keyup.enter="submit" />

KeyboardEvent.key로 노출된 유효한 키 이름을 kebab-case로 바꿔 수식어로 직접 쓸 수 있어요.

<input @keyup.page-down="onPageDown" />

이 예시는 $event.key'PageDown'일 때만 호출돼요.

키 별칭

.enter, .tab, .delete(Delete·Backspace 둘 다 캡처), .esc, .space, .up, .down, .left, .right가 제공돼요.

시스템 수식어 키

.ctrl, .alt, .shift, .meta 수식어로 해당 수식어 키가 눌린 상태에서만 마우스·키보드 리스너를 트리거해요. Mac에서 meta는 command 키(⌘), Windows에서는 Windows 키(⊞)예요.

<!-- Alt + Enter -->
<input @keyup.alt.enter="clear" />

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

.exact 수식어

.exact는 이벤트 트리거에 필요한 시스템 수식어의 정확한 조합을 제어할 수 있게 해줘요.

<!-- Alt 나 Shift 가 눌려도 발동 -->
<button @click.ctrl="onClick">A</button>

<!-- Ctrl 만 정확히 눌렸을 때만 발동 -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- 시스템 수식어가 하나도 눌리지 않았을 때만 발동 -->
<button @click.exact="onClick">A</button>

마우스 버튼 수식어

.left, .right, .middle 수식어는 특정 마우스 버튼으로 트리거된 이벤트로 핸들러를 제한해요. 이 이름들은 실제 물리 버튼이 아니라 "main", "secondary", "auxiliary" 포인팅 장치 이벤트 트리거를 나타낸다는 점을 유의하세요.

더 알아보기