써치킴의 우당탕탕 개발 블로그

[Vue.js][Ch2][Vue 문법] 이벤트 핸들링 - 이벤트 수식어 본문

완벽하게 Vue.js

[Vue.js][Ch2][Vue 문법] 이벤트 핸들링 - 이벤트 수식어

써치킴 2022. 4. 9. 02:04

event.preventDefault();

기본동작 방지

 
App.vue
<template>
  <a href="https://naver.com"
    target="_blank"
    @click="handler">
    NAVER
    </a>
</template>

<script>
export default {
  methods: {
    handler(event) {
      event.preventDefault();   // a 태그의 기본동작 방지
      console.log('ABC');
    }
  }
}
</script>

출력 

이벤트 핸들러 내부에서 event.preventDefault() 또는 event.stopPropagation()를 호출하는 것은 메소드 내에서 쉽게할 수 있지만,

메소드 내에선 DOM 이벤트 세부 사항을 처리하는 대신 데이터 로직에 대한 메소드만 사용할 수 있으면 더 좋다.

이 문제를 해결하기 위해 Vue는 v-on이벤트에 이벤트 수식어를 제공한다.

 

Vue.js에서 이벤트 수식어를 붙이는걸로 더 단순화하여 사용할 수 있게 제공!

이벤트 수식어 @event.prevent

기본 동작 방지

 

App.vue

<template>
  <a href="https://naver.com"
    target="_blank"
    @click.prevent="handler">
    NAVER
    </a>
</template>

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

=> NAVER를 클릭해도 아무런 동작하지 않는다.

이벤트 수식어 @event.once

특정 이벤트가 발생했을 때, 메소드를 단 한번만 실행

<template>
  <a href="https://naver.com"
    target="_blank"
    @click.once="handler">
    NAVER
    </a>
</template>

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

NAVER를 계속 클릭해도 콘솔에 ABC가 한번만 출력된다.

이벤트 수식어는 체이닝이 가능하다.

App.vue

<template>
  <a href="https://naver.com"
    target="_blank"
    @click.prevent.once="handler">    <!-- 기본동작 방지 + handler 메소드 한번만 실행 -->
    NAVER
    </a>
</template>

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

event.stopPropagation();

이벤트 전파 방지

 

App.vue

<template>
  <div 
    class="parent"
    @click="handlerA">
    <div
      class="child"
      @click="handlerB"></div> 
      <!-- class가 child인 div 태그를 클릭하면 
      child와 동일 영역인 parent 태그를 클릭한 것과 같기 때문에 콘솔에 B, A가 출력됨
      -> 이벤트 버블링 
      => 이벤트 버블링 방지를 위해 event.stopPropagation(); 사용
      -->
  </div>
</template>

<script>
export default {
  methods: {
    handlerA() {
      console.log('A');
    },
    handlerB(event) {
      event.stopPropagation();    // 이벤트 전파 방지
      console.log('B');
    }
  }
}
</script>

<style scoped lang="scss">
  .parent {
    width: 200px;
    height: 100px;
    background-color: royalblue;
    margin: 10px;
    padding: 10px;
    .child {
      width: 100px;
      height: 100px;
      background-color: orange;
    }
  }
</style>

출력

이벤트 수식어 @event.stop 

이벤트 전파 방지 

 

App.vue

<template>
  <div 
    class="parent"
    @click="handlerA">
    <div
      class="child"
      @click.stop="handlerB"></div> 
      <!-- class가 child인 div 태그를 클릭하면 
      child와 동일 영역인 parent 태그를 클릭한 것과 같기 때문에 콘솔에 B, A가 출력됨
      -> 이벤트 버블링 
      => 이벤트 버블링 방지를 위해 .stop 이벤트 수식어 사용
      -->
  </div>
</template>

<script>
export default {
  methods: {
    handlerA() {
      console.log('A');
    },
    handlerB(event) {
      console.log('B');
    }
  }
}
</script>

<style scoped lang="scss">
  .parent {
    width: 200px;
    height: 100px;
    background-color: royalblue;
    margin: 10px;
    padding: 10px;
    .child {
      width: 100px;
      height: 100px;
      background-color: orange;
    }
  }
</style>

class가 child인 div 태그를 클릭하면 child와 동일 영역인 parent 태그를 클릭한 것과 같기 때문에 콘솔에 B, A가 출력됨

 -> 이벤트 버블링 

.stop 이벤트 수식어를 사용하여 이벤트 버블링을 방지한다.

Class가 child인 div 태그를 클릭하면 콘솔애 'B'가 출력된다.

이벤트 캡처링

부모 요소가 자식 요소에게 영향을 주는 것.

이벤트 버블링과 반대되는 개념이다.

 

App.vue

<template>
  <div 
    class="parent"
    @click.capture="handlerA">
    <!-- class가 child인 div 태그는 parent 태그의 영역이기 때문에
    .capture를 통해 parent 태그(부모 영역)를 먼저 동작시키고 child(자식 영역) 태그를 동작시킴
    -> 이벤트 캡처링 (이벤트 버블링과 반대되는 개념)
    -->
    <div
      class="child"
      @click="handlerB"></div> 
  </div>
</template>

<script>
export default {
  methods: {
    handlerA() {
      console.log('A');
    },
    handlerB(event) {
      console.log('B');
    }
  }
}
</script>

<style scoped lang="scss">
  .parent {
    width: 200px;
    height: 100px;
    background-color: royalblue;
    margin: 10px;
    padding: 10px;
    .child {
      width: 100px;
      height: 100px;
      background-color: orange;
    }
  }
</style>

class가 child인 div 태그는 parent 태그의 영역이기 때문에 parent 태그에 .capture 이벤트 수식어를 사용하여

parent 태그(부모 영역)를 먼저 동작시키고 child(자식 영역) 태그를 동작시킴

parent 태그가 먼저 출력된다.

Parent 태그의 메소드만 출력하고 싶다면 

@click.capture.stop 수식어를 사용해

.capture를 통해 A가 먼저 출력되고 .stop을 통해 버블링을 방지한다.

<template>
  <div 
    class="parent"
    @click.capture.stop="handlerA">
    <!-- class가 child인 div 태그는 parent 태그의 영역이기 때문에
    .capture를 통해 parent 태그(부모 영역)를 먼저 동작시키고 child(자식 영역) 태그를 동작시킴
    -> 이벤트 캡처링 (이벤트 버블링과 반대되는 개념)
    -->
    <div
      class="child"
      @click="handlerB"></div> 
  </div>
</template>

이벤트 수식어 @event.self

event.target이 엘리먼트(영역) 자체인 경우에만 동작한다 => 자기 자신의 영역에만 event가 일어나면 동작한다.

자식 엘리먼트는 처리되지 않는다.

<template>
  <div 
    class="parent"
    @click.self="handlerA">
    <div
      class="child"></div> 
  </div>
</template>

클래스가 parent인 보여지는 부분을 클릭해야 handlerA 메소드가 동작한다.

event.target

클릭된 그 요소를 지칭

event.currentTarget

함수에 연결이 되어져 있는 이벤트의 요소를 지칭

 

App.vue

<template>
  <div 
    class="parent"
    @click.="handlerA">
    <div
      class="child"></div> 
  </div>
</template>

<script>
export default {
  methods: {
    handlerA(evnet) {
      /* 
      target : 클릭된 그 요소를 지칭
      currentTarget : 함수에 연결이 되어져 있는 이벤트의 요소를 지칭
      */
      console.log(evnet.target);
      console.log(evnet.currentTarget);
    },
    handlerB(event) {
      console.log('B');
    }
  }
}
</script>

<style scoped lang="scss">
  .parent {
    width: 200px;
    height: 100px;
    background-color: royalblue;
    margin: 10px;
    padding: 10px;
    .child {
      width: 100px;
      height: 100px;
      background-color: orange;
    }
  }
</style>

 출력

@wheel

마우스 휠으로 스크롤 이동할 때의 이벤트

이벤트 수식어 @event.passive

이벤트와 메소드 실행 로직을 분리 -> 사용자의 경험을 향상시켜줌

 

App.vue

<template>
  <div 
    class="parent"
    @wheel.passive="handler">   <!-- 마우스 휠으로 스크롤 이동할 때의 이벤트 -->
    <div class="child"></div> 
  </div>
</template>

<script>
export default {
  methods: {
    handler(event) {
      /* 
      휠 이동할 때마다 for문 안의 명령이 10000번 동작
      -> 과부하로 인한 버벅임 발생 
      => .passive를 통해 로직과 스크롤을 독립시켜줌
      */ 
      for (let i = 0; i < 10000; i += 1) {
        console.log(event);
      }
      console.log(event);
    }
  }
}
</script>

<style scoped lang="scss">
  .parent {
    width: 200px;
    height: 100px;
    background-color: royalblue;
    margin: 10px;
    padding: 10px;
    overflow: auto;
    .child {
      width: 100px;
      height: 2000px;
      background-color: orange;
    }
  }
</style>
 

 

Comments