Event

  • vue에서는 v-on 디렉티브(@ 기호)를 사용하여 DOM 이벤트를 감지하고 핸들러를 실행한다.
  • 컴포지션 API에서는 setup() 함수 내부에서 이벤트 핸들러를 정의하고 바인딩 한다.

이벤트 처리

이벤트 처리 - 인라인 핸들러 방식

  • v-on을 활용하여 Vue와 바인딩된 객체 활용할 수 있는 script를 생성하여 처리
<script setup>
import { ref } from 'vue';

const amount = ref(0); // 금액
const balance = ref(0); // 잔고
</script>

<template>
  <div class="child">
    금액 : <input type="text" v-model.number="amount" />
    <button
      @click="
        balance += amount;
        amount = 0;
      "
    >
      입금
    </button>
    <button
      @click="
        balance -= amount;
        amount = 0;
      "
    >
      출금
    </button>
    잔고 : {{ balance }}
  </div>
</template>

이벤트 처리 - 메서드 핸들러

  • @를 통해 Vue 내부의 메서드 핸들러와 연결하는 방식이다.
  • 긴 이벤트 처리에도 적합하고 Vue 코드에서 이벤트 처리 코드를 작성 가능하다.
  • 가급적 해당 방법을 사용하는 것을 권장, 사유는 코드 관리가 편해진다.
<script setup>
import { ref } from 'vue';

const amount = ref(0); // 금액
const balance = ref(0); // 잔고

const deposit = () => {
  if (amount.value <= 0) {
    alert('0보다 큰 값을 입력하세요.');
    return;
  }
  balance.value += amount.value;
  amount.value = 0;
};

const withdraw = () => {
  if (amount.value <= 0) {
    alert('0보다 큰 값을 입력하세요.');
  } else if (amount.value > balance.value) {
    alert('잔액이 부족합니다.');
  } else {
    balance.value -= amount.value;
    amount.value = 0;
  }
};
</script>

<template>
  <div class="child">
    금액 : <input type="text" v-model.number="amount" /><br />
    <button @click="deposit">입금</button>
    <button @click="withdraw">출금</button><br />
    <b>잔고 : {{ balance }}</b
    ><br />
  </div>
</template>

이벤트 처리 - 핸들러 + input 이벤트

  • 일반적인 이벤트 핸들러를 생성하면 (e)=>{} 타입으로 생성되어 e 객체 활용 가능
  • 만일, 사용자가 정의한 인자와 event 객체를 활용하고 싶은 경우, $event로 인자 처리가 가능
<script setup>
import { ref } from 'vue';

const value1 = ref('');
const value2 = ref('');

const changeValue = (e) => {
  value2.value = e.target.value;
};

const userClickEvent = (msg) => {
  alert(msg);
};

const userClickEvent2 = (msg, event) => {
  event.preventDefault();
  alert(`${msg}, ${event.target.innerText}`);
};
</script>

<template>
  <div class="child">
    <h3>인라인 이벤트 핸들러에서 e처리 방법</h3>
    value1 : {{ value1 }}<br />
    <input
      type="text"
      :value="value1"
      @input="
        (e) => {
          value1 = e.target.value;
        }
      "
    />

    <h3>함수로 분리한 이벤트 핸들러에서 e처리 방법</h3>
    value2 : {{ value2 }}<br />
    <input type="text" :value="value2" @input="changeValue" />

    <h3>사용자가 정의한 인자 전달 예제</h3>
    <button @click="userClickEvent('message 1입니다.')">사용자 정의 인자 전달</button>

    <h3>사용자가 정의한 인자 + event => $event 인자 전달</h3>
    <button @click="userClickEvent2('message 2입니다.', $event)">사용자 정의 인자 + event</button>
  </div>
</template>

이벤트 수식어

기본적인 수식어

  • .stop : 이벤트 전파 중지 (event.stopPropagation())
  • .prevent : 기본 동작 방지 (event.preventDefault())
  • .self : 이벤트가 자기 자신에서만 발생할 때 실행
  • .capture : 캡처 단계에서 실행
  • .once : 한 번만 실행됨
  • .passive : event.preventDefault()가 있어도 기본 동작을 수행

사용은 아래와 같이 사용하면 된다.

<script setup>

const doStop = () => alert('doStop 클릭, 이벤트 전파 안됨!');
const doThat = () => alert("doThat 클릭!");

</script>

<template>
    <button @click.stop="doStop">이벤트가 전파 방지 버튼</button> <br>

    <!-- 여러 수식어 조합 -->
    <button @click.stop.prevent="doThat">전파 + 기본동작 방지</button><br><br>
</template>

마우스 클릭 관련

  • .left : 왼쪽 버튼 클릭
  • .right : 오른쪽 버튼 클릭
  • .middle : 가운데 버튼 클릭
<script setup>
const leftClick = () => alert('왼쪽 클릭됨!');
const rightClick = () => alert('오른쪽 클릭됨!');
const middleClick = () => alert('가운데 클릭됨!');
</script>
<template>
  <div class="child">
    <button @click.left="leftClick">왼쪽 클릭</button>
    <button @click.right="rightClick">오른쪽 클릭</button>
    <button @click.middle="middleClick">가운데 클릭</button>
  </div>
</template>

<style lang="scss" scoped></style>

키입력 관련

  • .enter : Enter 키가 눌렸을 때 실행
  • .tab : Tab 키
  • .delete : Delete & Backspace 키
  • .esc : Escape 키
  • .space : Space 키
  • .up : 화살표 위 키
  • .down : 화살표 아래 키
  • .left : 화살표 왼쪽 키
  • .right : 화살표 오른쪽 키
<script setup>
const submit = () => alert('제출됨!');
const deleteItem = () => alert('삭제됨!');
const escClick = () => alert('esc 클릭됨!');
</script>
<template>
  <div class="child">
    Enter 키를 눌러 제출 : <input type="text" @keyup.enter="submit" /> <br />
    delete 키를 눌러 삭제 : <input type="text" @keyup.delete="deleteItem" /> <br />
    esc 키를 눌러 취소 : <input type="text" @keyup.esc="escClick" /> <br />
  </div>
</template>

시스템 관련

  • .ctrl : Ctrl 키를 누른 상태에서만 실행
  • .alt : Alt 키를 누른 상태에서만 실행
  • .shift : Shift 키를 누른 상태에서만 실행
  • .meta : Mac의 ⌘(Command) 또는 Windows의 ⊞(Windows)
<script setup>
const clear = () => alert('입력값 초기화!');
const doSomething = () => alert('Ctrl + 클릭 실행됨!');
const onClick = () => alert('클릭 됨');
const onCtrlClick = () => alert('ctrl + 클릭 됨');
</script>
<template>
  Alt+Enter 초기화 : <input @keyup.alt.enter="clear" /> <br />
  <button @click.ctrl="doSomething">Ctrl + 클릭 실행</button> <br />
  <button @click.ctrl.exact="onCtrlClick">Ctrl만 눌러야 실행됨</button> <br />
  <button @click.exact="onClick">다른 키 없이 클릭해야 실행됨</button> <br />
</template>