blog

Vue 이벤트 핸들러: 인라인 핸들러와 메서드 핸들러의 차이

Front-end / Vue#Vue#v-on#이벤트 핸들러#React

@click="openModal('severeResult')"처럼 인자를 넘겨 호출하는 코드를 보면 "렌더링할 때 바로 실행되는 것 아닌가?" 하는 의문이 든다. React의 onClick={openModal('severeResult')}가 실제로 그렇게 동작하기 때문이다. Vue에서는 즉시 실행되지 않는다.

Vue 템플릿 컴파일러의 두 가지 처리

v-on(@)의 값은 컴파일러가 형태를 보고 다르게 처리한다.

메서드 핸들러

값이 함수 이름이나 경로(openModal, foo.bar)면 그 함수를 그대로 핸들러로 등록한다. 첫 번째 인자로 네이티브 이벤트 객체가 전달된다.

<button @click="openModal">열기</button>
<!-- 대략 onClick: openModal -->

인라인 핸들러

값이 호출식이나 문장(openModal('x'), count++, $emit('result', type))이면 컴파일러가 화살표 함수로 감싼다.

<button @click="openModal('severeResult')">열기</button>
<!-- 대략 onClick: $event => openModal('severeResult') -->

<input @change="$emit('result', answer.type)" />
<!-- 대략 onChange: $event => $emit('result', answer.type) -->

그래서 openModal('severeResult')는 클릭할 때만 실행된다. $emit이 특별 취급되는 것이 아니라, 호출식이면 모두 같은 규칙으로 감싸진다. @click="() => openModal('severeResult')"처럼 직접 감싸도 동작은 같지만 필요하지 않다.

인라인 핸들러에서 이벤트 객체 쓰기

인자와 이벤트 객체가 모두 필요하면 $event를 넘기거나 화살표 함수를 쓴다.

<button @click="openModal('severeResult', $event)">열기</button>
<button @click="(event) => openModal('severeResult', event)">열기</button>

실제로 즉시 실행되는 경우

  • React JSX: onClick={openModal('x')}는 렌더링 중에 실행된다. onClick={() => openModal('x')}로 감싸야 한다.
  • Vue의 v-bind로 함수 prop 전달: :on-close="closeModal('x')"는 v-on이 아니라 일반 바인딩이라 렌더링 때 호출되고 그 반환값이 전달된다. :on-close="() => closeModal('x')"로 감싼다.
  • Vue 렌더 함수/JSX: h('button', { onClick: openModal('x') })도 즉시 실행된다.

정리

코드처리실행 시점
@click="openModal"함수 그대로 등록클릭 시 (이벤트 객체 전달)
@click="openModal('x')"$event => openModal('x')로 감쌈클릭 시
@change="$emit('result', v)"$event => $emit('result', v)로 감쌈change 시
:on-close="closeModal('x')"일반 바인딩렌더링 시 ❌
React onClick={openModal('x')}일반 표현식렌더링 시 ❌