[Vue.js] DOM event 핸들링 방법
v-bind 디렉티브는 인스턴스의 데이터를 HTML 속성으로 바인딩하여 렌더링합니다. 이와는 반대로 v-on 디렉티브는 인스턴스에서 DOM 이벤트를 수신할 수 있습니다.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<button v-on:click="increase">
Click me
</button>
<p>{{ counter }}</p>
</div>
new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
increase: function() {
this.counter++;
}
}
});
위의 예시는 counter 라는 데이터를 렌더링하고 있고, v-on 디렉티브를 이용하여 버튼의 click 이벤트를 리스닝하고 있는 상황입니다. 만약 버튼이 클릭되면 인스턴스는 이벤트를 수신하여 "increase" 메서드를 수행합니다. 그 결과 counter++ 가 수행되고, counter가 증가함에 따라 Interpolation으로 렌더링되고 있는 숫자가 1 증가합니다.
Getting Event Object
vue.js 는 v-on 디렉티브로 리스닝하고 있는 이벤트에 대해서 Event Object를 파라미터로 받을 수 있습니다. 예제 코드를 보겠습니다.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<button v-on:click="increase">
Click me
</button>
<p>{{ counter }}</p>
<p v-on:mousemove="updateCoordinates">Coordinates: {{ x }} / {{ y }}</p>
</div>
new Vue({
el: '#app',
data: {
counter: 0,
x: 0,
y: 0
},
methods: {
increase: function() {
this.counter++;
},
updateCoordinates: function(event) {
this.x = event.clientX;
this.y = event.clientY;
}
}
});
가장 아래의 <p> 태그는 v-on 디렉티브로 mousemove 이벤트에 대해서 리스닝하고 있으며 이에 호출되는 updateCoordinates 함수는 인스턴스의 프로퍼티인 x, y를 마우스의 좌표 값인 clientX, clientY로 변경하고 있습니다. clientX, clientY는 event 오브젝트의 기본 속성입니다.
위 코드의 결과로 가장 아래의 <p> 태그위에서 마우스가 움직이면 mouse event가 발생하여 이를 수신하고 있는 함수가 호출되어 새롭게 변경된 x, y 값이 렌더링 됩니다.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<button v-on:click="increase(100)">
Click me
</button>
<p>{{ counter }}</p>
<p v-on:mousemove="updateCoordinates">Coordinates: {{ x }} / {{ y }}</p>
</div>
new Vue({
el: '#app',
data: {
counter: 0,
x: 0,
y: 0
},
methods: {
increase: function(step) {
this.counter += step;
},
updateCoordinates: function(event) {
this.x = event.clientX;
this.y = event.clientY;
}
}
});
HTML 코드 상에서 버튼과 리스닝하고 있는 메서드를 보면 "increase(100)" 과 같이 선언하여 호출되는 함수에 대해서 인자 값을 전달할 수 있습니다. vue 인스턴스는 increase 함수에서 step 이라는 이름의 파라미터로 해당 값을 받을 수 있습니다.
그와 동시에 이벤트에 대한 오브젝트도 함께 받고 싶다면, $event 변수를 이용하면 됩니다. 이 변수 이름은 예약되어 있는 이름이므로, 오버라이드하거나 오타로 잘못입력하지 않도록 주의해야합니다.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<button v-on:click="increase(100, $event)">
Click me
</button>
<p>{{ counter }}</p>
<p v-on:mousemove="updateCoordinates">Coordinates: {{ x }} / {{ y }}</p>
</div>
new Vue({
el: '#app',
data: {
counter: 0,
x: 0,
y: 0
},
methods: {
increase: function(step, event) {
this.counter += step;
},
updateCoordinates: function(event) {
this.x = event.clientX;
this.y = event.clientY;
}
}
});
Event Modifiers
리스닝되고 있는 이벤트는 수식어를 통해서 별도로 다른 로직에 대한 메소드를 처리하도록 할 수 있습니다.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<button v-on:click="increase(100)">
Click me
</button>
<p>{{ counter }}</p>
<p v-on:mousemove="updateCoordinates">
Coordinates: {{ x }} / {{ y }}
- <span v-on:mousemove="dummy">DEAD SPOT</span>
</p>
</div>
new Vue({
el: '#app',
data: {
counter: 0,
x: 0,
y: 0
},
methods: {
increase: function(step, event) {
this.counter += step;
},
updateCoordinates: function(event) {
this.x = event.clientX;
this.y = event.clientY;
},
dummy: function(event) {
event.stopPropagation();
}
}
});
위 코드는 가장 아래 <p> 태그 영역의 마우스 이벤트를 리스닝하여 updateCoordinates 함수를 처리하지만, 그 안에 있는 <span> 태그의 영역에서는 event.stopPropagation() 처리를 하여 이벤트 전파를 막고 있기 때문에 x, y 의 값을 변경하지 않습니다.
위 코드는 이벤트 수식어를 통해 dummy 함수를 없애고, 아래와 같이 간단하게 구성할 수 있습니다.
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<button v-on:click="increase(100)">
Click me
</button>
<p>{{ counter }}</p>
<p v-on:mousemove="updateCoordinates">
Coordinates: {{ x }} / {{ y }}
- <span v-on:mousemove.stop="">DEAD SPOT</span>
</p>
</div>
.stop 수식어는 해당 이벤트의 전파가 중단되도록 합니다. 그리고 이벤트 수식어는 " .stop.prevent " 와 같이 체이닝이 가능합니다.
그 외에도 다양한 이벤트 수식어가 존재합니다.
<!-- 클릭 이벤트 전파가 중단됩니다 -->
<a v-on:click.stop="doThis"></a>
<!-- 제출 이벤트가 페이지를 다시 로드 하지 않습니다 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 수식어는 체이닝 가능합니다 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 단순히 수식어만 사용할 수 있습니다 -->
<form v-on:submit.prevent></form>
<!-- 이벤트 리스너를 추가할 때 캡처모드를 사용합니다 -->
<!-- 즉, 내부 엘리먼트를 대상으로 하는 이벤트가 해당 엘리먼트에서 처리되기 전에 여기서 처리합니다. -->
<div v-on:click.capture="doThis">...</div>
<!-- event.target이 엘리먼트 자체인 경우에만 트리거를 처리합니다 -->
<!-- 자식 엘리먼트에서는 안됩니다 -->
<div v-on:click.self="doThat">...</div>
출처 : https://kr.vuejs.org/v2/guide/events.html
이벤트 핸들링 — Vue.js
Vue.js - 프로그레시브 자바스크립트 프레임워크
kr.vuejs.org
참고자료
https://kr.vuejs.org/v2/guide/events.html
이벤트 핸들링 — Vue.js
Vue.js - 프로그레시브 자바스크립트 프레임워크
kr.vuejs.org
Udemy 강의