Vue.js: Vue 문법 Ep.6 이벤트 핸들링

이벤트 핸들링


Vue.js: 이벤트 핸들링

  • 이벤트 리스닝

    v-on 디렉티브를 @기호로 작성이 가능하며, DOM 이벤트를 듣고 트리거 될 때와 자바스크립트를 실행할 때 사용한다.

    <button @click="count += 1"></button>
    
  • 메소드 핸들러

    위와 같은 인라인 핸들러에서는 복잡한 논리를 사용하기 힘들다. 따라서 메소드에 복잡한 내용들을 작성하고 해당 메소드 명을 이벤트 핸들러로 사용한다.

    methods: {  
      greet(event) {   
        alert(`안녕 ${this.name}!`)
        if (event) {      
          alert(event.target.tagName)    
        }  
      }
    }
    
    <button @click="greet">환영하기</button>
    
  • 인라인 핸들러에서 메소드 호출

    메서드 이름을 직접 바인딩하지 않고 인라인 핸들러에서 메서드를 호출할 수 있다. 결과로 이벤트 객체 대신 사용자 지정 인자를 출력할 수 있다.

    methods: {
      handler(msg) {
        console.log(msg)
      }
    }
    
      
    <button @click="handler('hello')">Click!</button>
    
    • 이벤트 객체와 인수 둘 다 사용하기

      vue에서 제공하는 문법 $event를 사용하면 된다.
      해당하는 이벤트가 연결되어져 있는 버튼에서 이벤트 객체가 나와서 $event 안으로 들어가게 된다.

      methods: {
        handler(msg,event) {
          console.log(msg)
        }
      }
      
          
      <button @click="handler('hello', $event)">Click!</button>
      
  • 여러가지 이벤트 핸들러 사용

    하나의 요소에 어떤 이벤트가 발생했을 때 실행할 메소드가 여러개라면, 해당 메소드를 쉼표로 구분한다.
    단, 주의할 점은 호출할때 메소드 명 뒤에 소괄호를 꼭 붙여야 한다. 소괄호를 사용하지 않으면 메소드가 호출되지 않는다.

    methods: {
      handlerA() {
        console.log('A')
      },
      handlerB() {
        console.log('B')
      }
    }
    
      
    <button @click="handlerA(),handlerB()">Click!</button>
    

    버튼을 한번만 클릭해도 메소드 두개가 동시에 작동된다.
    콘솔창에서 확인해 보면, A와 B가 동시에 출력된 것을 볼 수 있다.

이벤트 핸들링: 이벤트 수식어


이벤트 핸들러 내에서 event.preventDefault()또는 event.stopPropagation()을 호출 자주 호출하게 된다. 메소드 내에서는 해당 작업을 쉽게 수행할 수 있지만 메소드가 데이터 처리 로직만 가지고 있다면 유지보수가 더욱 용이할 것이다.
그렇기에 이벤트 수식어를 사용하여 유지보수가 용이하도록 만든다.

  • 이벤트 수식어 체이닝

    이벤트 수식어는 체이닝이 가능하다.
    체이닝 형태로 여러가지 수식어를 붙여서 사용할 수 있다.

    <div @click.prevent.once="handler"></div>
    
  • preventDefault

    preventDefault는 기본 동작을 방지하는 것이다.
    예시를 들자면, html에서 a태그는 기본적으로 페이지 링크를 연결해주는 동작을 가지고 있다. a태그의 기본동작은 링크 연결인 것이다.
    즉, html이 기본적으로 가지고 있는 동작이라고 생각하면 된다.

    오직 event.preventDefault만 사용한다면 a태그가 가지고 있는 기본 동작이 방지가 되면서 동작하지 않게 되고 다음 로직으로 넘어가게 된다.

  • .prevent

    preventDefault라는 기능을 prevent 이름만 작성하여 사용할 수 있게 한다.

  • .once

    특정 이벤트가 발생했을 때 해당하는 메소드를 단 한번만 실행해준다.
    동작을 다시 실행하더라도 해당 메소드는 더 이상 실행되지 않는다.

  • .stop

    해당 수식어는 stopPropagation 메소드를 간단하게 사용하기 위해 만든 수식어이다.

    이벤트 버블링을 방지할 때 자주 사용한다.
    버블링이 발생하지 않기를 원하는 영역에 해당 수식어를 사용하면 버블링이 발생하지 않고 원하는 부분의 메소드만 실행하게 된다.
    즉, 전파를 방해하는 역할을 한다.

    이벤트 버블링
    마치 거품이 일어나듯이 점점 확산되는 개념이다.
    a 박스(부모요소) 안에 b 박스(자식요소)가 존재할 때, a 박스 부분을 클릭하면 a 메소드만 출력되지만 b박스 부분을 클릭하면 b 메소드가 실행된 후 a 메소드도 실행된다.
    이는, a박스가 b 박스를 감싸고 있기 때문이다. 이런 현상이 이벤트 버블링이다.

  • .capture

    해당 수식어는 버블링의 반대 개념인 캡처링을 발생시키는 수식어이다.
    이벤트 실행의 순서를 역으로 진행하게 만든다.

    이벤트 캡처링(Event Capturing)
    이벤트 버블링의 반대가 되는 개념이다.
    이벤트 버블링은 자식요소(b박스)가 먼저 실행되고 부모요소(a박스)가 실행이 된다.
    하지만, 이벤트 캡처링은 부모요소가 먼저 실행되고 그 이후에 자식요소가 실행되도록 만든다.

    • 만약 거꾸로 버블링을 방지시키고 싶다면?

      자식요소 부분을 클릭했을 때, 부모요소만 실행되고 자식요소가 실행되지 않게 하고 싶다면 부모요소 부분에 .capture.stop을 작성하면 된다.
      캡처링으로 인해 부모요소가 먼저 실행이 되고 이후에 자식요소가 실행을 하려 할때 stop 수식어로 인해 실행이 멈추면서 자식요소는 실행되지 않는다.

  • .self

    해당 수식어가 붙어있는 해당 영역을 정확하게 클릭을 했을 때에만 해당 이벤트가 동작하도록 만들어 준다.

    예를 들면, 부모요소 위에 자식요소 버튼이 존재한다. 자식요소에는 click 이벤트가 존재하지 않는다.
    부모요소에 self 수식어를 사용하지 않았다면 자식요소를 클릭해도 부모요소의 메소드가 실행된다. 버블링으로 인해 자식요소 뒤에 있는 부모요소가 실행되는 것이다.
    부모요소에 self 수식어를 사용한다면, 자식요소를 클릭해도 이벤트가 실행되지 않는다. 오직 self 수식어가 붙어있는 영역인 부모요소의 이벤트만 실행되게 된다.
    정확이 말하자면, 모든 영역이 부모요소인 것은 맞지만 자식요소로 인해 자식요소가 존재하는 부분은 노출되어져 있지 않다. 자식요소가 해당 부분을 가리기 때문이다.
    그렇기에 self는 오직 부모요소가 노출되어져 있는 부분만을 클릭했을 때 이벤트가 실행하게 만든다.

  • .passive

    처리해야 하는 로직이 굉장히 많이 존재할 때 동작 실행이 느려지게 된다.
    많은 양의 로직과 브라우저에 보이는 화면을 동시에 처리하기 때문이다.

    passive 수식어를 사용하게 되면 로직 처리와 브라우저 출력을 독립시킬 수 있다. 그렇게 되면 브라우저에서 보이는 렉(동작 느려짐)이 줄어들고 로직 처리는 따로 돌아가게 된다. 사용자 입장에서 화면을 이용할 때 편리하며, 로직은 내부적으로 따로 돌아가기 때문에 문제가 되지 않는다.

    <div @scroll.passive="onScroll">...</div>
    

    즉, passive는 로직처리가 많은 메소드를 호출하는 요소에 사용하면 좋다.

    추가로, passive는 prevent와 함께 사용해서는 안된다. passive는 브라우저에게 이벤트의 기본동작을 방해(prevent)하지 않겠다는 의미를 가지기 때문이다.

이벤트 핸들링: 키 수식어


input에서 enter 키를 입력했을 때 콘솔창에 Enter라는 문구가 출력되도록 코드를 작성했다.

key 요소에 값으로 Enter가 들어왔을 때, 콘솔창에 Enter!! 문구를 출력하도록 if문을 사용하여 작성했다.

<template>
  <input
    type="text"
    @keydown="handler" />
</template>

<script>
export default {
  methods: {
    handler(event) {
      if (event.key === 'Enter') {
        console.log('Enter!!')
      }
    }
  }
}
</script>

하지만, 이렇게 if문을 사용하지 않고 간단하게 키 수식어를 통해 작동되도록 할 수 있다.

input에 a를 제외한 나머지 키들을 입력하다가 a키를 누르면 콘솔창에 Enter 문구가 출력되도록 작성했다.
이제는 if 문이 아니라 keydown 이벤트 뒤에 a 수식어만 추가해주면 된다.

<template>
  <input
    type="text"
    @keydown.a="handler" />
</template>

<script>
export default {
  methods: {
    handler() {
      console.log('Enter!!')
    }
  }
}
</script>

위 코드 처럼 원하는 키를 눌렀을 때 어떤 동작이 실행되도록 만들고 싶다면 이벤트 뒤에 원하는 키 수식어를 작성하면 된다.
단, 수식어는 꼭 케밥케이스로 작성해야 한다.

예) a ⇒ .a / enter ⇒ .enter

추가로, 해당 키 수식어 또한 체이닝이 가능하다.
@keydown.ctrl.a=”handler”
a키만 누르면 메소드가 실행되지 않고 ctrl 키와 a키를 같이 눌러야 메소드가 실행된다.

Comments