일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- H-index
- 모던 자바 인 액션
- K번째수
- 다리를 지나는 트럭
- 검색 기능 확장
- @Data
- Java
- 스프링 스케쥴러
- 프로그래머스
- 스택/큐
- 영속 자료구조
- 가장 큰 수
- 정렬
- 해시
- 루씬 인 액션
- @Getter
- 커링
- 고차원 함수
- 전화번호 목록
- 완주하지 못한 선수
- 크론 표현식
- @configuration
- 롬복 어노테이션
- 알고리즘
- 기능개발
- 코딩 테스트
- 쿠버네티스
- kubenetes
- @Setter
- @EnableScheduling
- Today
- Total
Today I Learned
이벤트 처리 본문
인라인 이벤트 처리
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>04-01</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<style>
.layout1 {
margin: 30px 30px 30px 30px;
}
</style>
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="example" class="container layout1">
<p><input type="text" v-model="amount" class="form-control" /></p>
<p>
<button id="deposit" @click="balance += parseInt(amount)" class="btn btn-primary">예금</button>
<button id="withdraw" @click="balance -= parseInt(amount)" class="btn btn-primary">인출</button>
</p>
<h3>계좌 잔고 : {{balance}}</h3>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#example",
data: {
amount: 0,
balance: 0,
}
})
</script>
</body>
</html>
v-on 디렉티브를 이용한 이벤트 처리
v-model로 amount 데이터 속성을 양방향 바인딩
v-on:click 디렉티브를 이용해 클릭 이벤트 처리를 수행
v-on 디렉티브는 @로 줄여쓸 수 있다. ( v-on:click = @click )
이벤트 핸들러 메서드
<div id="example" class="container layout1">
<p><input type="text" v-model="amount" class="form-control" /></p>
<p>
<button id="deposit" v-on:click="deposit($event)" class="btn btn-primary">예금</button>
<button id="withdraw" v-on:click="withdraw" class="btn btn-primary">인출</button>
</p>
<h3>계좌 잔고 : {{balance}}</h3>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#example",
data: {
amount: 0,
balance: 0,
},
methods: {
deposit: function(e) {
var amt = parseInt(this.amount);
if (amt <= 0) {
alert("0보다 큰 값을 예금해야 합니다");
} else {
this.balance += amt;
}
},
withdraw: function(e) {
var amt = parseInt(this.amount);
if (amt <= 0) {
alert("0보다 큰 값을 인출할 수 있습니다");
} else if (amt > this.balance) {
alert("잔고보다 많은 금액을 인출할 수 없습니다");
} else {
this.balance -= amt;
}
}
}
})
</script>
Vue 인스턴스에 deposit, withdraw 메서드를 작성
메서드에 금액과 계좌 잔고에 따른 유효성 검사 기능 추가
이벤트 객체
이벤트를 처리하는 메서드는 첫 번째 파라미터로 이벤트 객체를 전달받음
Vue.js의 이벤트 객체는 W3C 표준 HTML, DOM Event 모델을 그대로 따르면서 추가적인 속성을 제공
→기존 자바스크립트의 이벤트 객체 정보를 거의 대부분 이용가능
- 이벤트 객체의 주요 공통 속성
속성명 | 설명 |
target | 이벤트가 발생한 HTML 요소를 리턴함 |
currentTarget | 이벤트리스너가 이벤트를 발생시키는 HTML 요소를 리턴함 |
path | 배열값, 이벤트 발생 HTML 요소로부터 document, window 객체로까지 거슬러 올라가는 경로를 나타냄 |
bubbles | 현재의 이벤트가 버블링을 일으키는 이벤트인지 여부를 리턴함 |
defaultPrevented | 기본 이벤트가 방지되었는지 여부를 나타냄 |
eventPhase |
이벤트 흐름의 단계를 나타냄 1 : 포착(CAPTURING_PHASE) 2 : 이벤트 발생(AT_TARGET) 3 : 버블링(BUBBLING_PHASE) |
srcElement | IE에서 사용되던 속성으로 target과 동일한 속성 |
- 키보드 이벤트 관련 속성
속성명 | 설명 |
altKey | ALT 키가 눌려졌는지 여부를 나타냄(true/false) |
shiftKey | SHIFT 키가 눌려졌는지 여부를 나타냄(true/false) |
ctrlKey | CTRL 키가 눌려졌는지 여부를 나타냄(true/false) |
metaKey | 메타키가 눌려졌는지 여부를 나타냄. 윈도우에서는 Window Key, macOS 에서는 Command Key |
Key | 이벤트에 의해 나타나는 키의 값을 리턴함. 대소문자 구분함 |
code |
이벤트를 발생시킨 키의 코드값을 리턴함 ex) A 키를 눌렀을때 "KeyA"를 리턴 |
KeyCode |
이벤트를 발생시킨 키보드의 고유 키코드 ex) a, A는 65를 리턴함 (대소문자 구분하지 않음) |
charCode | keypress 이벤트가 발생될 때 Unicode 캐릭터 코드를 리턴함 |
location | 디바이스에서의 키 위치값, 일반 키보드는 이 값이 모두 0이므로 이용할 수 없음 |
- 마우스 이벤트 관련 속성
속성명 | 설명 |
altKey, shiftKey ctrlKey, metaKey |
키보드 이벤트 관련 속성 참조 |
button |
이벤트를 발생시킨 마우스 버튼 0 : 마우스 왼쪽 버튼 1 : 마우스 휠 2 : 마우스 오른쪽 버튼 |
buttons |
마우스 이벤트가 발생한 후에 눌려져있는 마우스 버튼의 값을 리턴함. 아래 값의 조합으로 이루어짐 1 : 마우스 왼쪽 버튼 2 : 마우스 오른쪽 버튼 4 : 마우스 휠 8 : 4번째 마우스 버튼 16 : 5번째 마우스 버튼 ex) 마우스 오른쪽 버튼, 휠을 누르고 있는 상태에서 왼쪽 버튼을 클릭할 경우 이 값은 6을 리턴함 |
clientX, clientY | 마우스 이벤트가 일어났을 때의 뷰포트(ViewPort) 영역상의 좌표, 이 좌표는 스크롤바를 내리더라도 좌표값에 영향을 받지 않음 |
layerX, layerY | 마우스 이벤트가 발생한 HTML 요소 영역상에서의 좌표 (IE 이외의 브라우저 사용) |
offsetX, offsetY | 마우스 이벤트가 발생한 HTML 요소 영역상에서의 좌표 (IE 브라우저 사용) |
pageX, pageY | 마우스 이벤트가 일어났을 때의 HTML 문서(Document) 영역상의 좌표 |
screenX, screenY | 마우스 이벤트가 일어났을 때의 모니터 화면(Screen) 영역상의 좌표 |
- 이벤트 객체의 주요 메서드
속성명 | 설명 |
preventDefault() | 기본 이벤트의 자동 실행을 중지시킴 |
stopPropagation() | 이벤트의 전파를 막음 |
기본이벤트
HTML 문서나 요소에 어떤 기능을 실행하도록 이미 정의되어 있는 이벤트
대표적인 기본 이벤트
- <a> 요소를 클릭했을 때 href 특성의 경로로 페이지를 이동시킴
- 브라우저 화면을 마우스 오른쪽 클릭했을 때 내장 컨텍스트 메뉴(ContextMenu)가 나타남
- <form> 요소 내부의 submit 버튼을 클릭했을 때 action 특성에 지정된 경로, method 특성에 지정된 방식으로 전송함
- <input type="text" ... /> 요소에 키보드를 누르면 입력한 문자가 텍스트 박스에 나타남
기본이벤트 실행을 중지시키는 방법
<div id="example" v-on:contextmenu.prevent="ctxStop">
<a href="https://facebook.com" @click="confirmFB">페이스북</a>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#example",
methods: {
ctxStop: function(e) {
},
confirmFB: function(e) {
if (!confirm("페이스북으로 이동할까요?")) {
e.preventDefault();
}
}
}
})
</script>
confirm 창에서 취소 버튼을 클릭하면 preventDefault() 메서드가 호출되어 <a> 요소의 기본이벤트인 URL 이동을 막음
이벤트 수식어(Event Modifier)를 통해서도 기본이벤트 제어 가능 → contextmenu.prevent로 컨텍스트메뉴 호출 막음
* 이벤트수식어 : 다양한 이벤트와 관련된 문제를 쉽게 해결하기 위해 제공
이벤트 전파와 버블링
HTML 문서의 이벤트 처리 3단계
- 1단계 : 이벤트 포착 단계 (CAPTURING_PHASE)
문서 내의 요소에서 이벤트가 발생했을 때 HTML 문서의 밖에서부터 이벤트를 발생시킨 HTML 요소까지 포착해 들어가는 단계 - 2단계 :이벤트 발생 단계 (RASING_PHASE)
이벤트를 발생시킨 요소에 다다르면 요소의 이벤트에 연결된 함수를 직접 호출시키는 단계 - 3단계 : 버블링 단계 (BUBBLING_PHASE)
이벤트가 발생한 요소로부터 상위 요소로 거슬러올라가면서 동일한 이벤트를 호출시키는 단계
이벤트 전파
<div id="example">
<div id="outer" @click="outerClick">
<div id="inner" @click="innerClick"></div>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#example",
methods: {
outerClick: function(e) {
console.log("### OUTER CLICK")
console.log("Event Phase : ", e.eventPhase);
console.log("Current Target : ", e.currentTarget);
console.log("Target : ", e.target);
//e.stopPropagation();
},
innerClick: function(e) {
console.log("### INNER CLICK")
console.log("Event Phase : ", e.eventPhase);
console.log("Current Target : ", e.currentTarget);
console.log("Target : ", e.target);
//e.stopPropagation();
}
}
})
</script>
#inner 요소를 클릭하면 #outer의 click 이벤트까지 실행된다.
일반적으로 이벤트 버블링은 막아야 할 작업 (#inner를 클릭했을 때 상위 요소로의 이벤트 전파는 막아야함)
→ 이를 위해 이벤트 객체의 stopPropagation() 메서드를 호출
코드에서 주석처리한 e.stopPropagation()을 사용하거나 @click 대신 @click.stop 이벤트 수식어로 대체 가능
이벤트 전파와 관련된 이벤트 수식어
- .stop : 이벤트 전파를 중단
- .capture : CAPTURING_PHASE 단계에서만 이벤트가 발생
- .self : RAISING_PHASE 단계에서만 이벤트가 발생
이벤트 객체의 주요 속성값 비교
#inner click | #outer click |
|
eventPhase | 2 (AT_TARGET) | 3 (BUBBLING) |
current target | #inner | #outer |
target | #inner | #inner (이벤트가 일어난 원본 요소) |
이벤트 수식어
once 수식어
한번만 이벤트를 발생시킴
<div id="example" class="container layout1">
<p><input type="text" v-model="amount" class="form-control" /></p>
<p>
<button id="create" v-on:click.once="specialEvent" class="btn btn-primary">
계좌 개설 10000원 이벤트</button>
<button id="deposit" v-on:click="deposit($event)" class="btn btn-primary">예금</button>
<button id="withdraw" v-on:click="withdraw" class="btn btn-primary">인출</button>
</p>
<h3>계좌 잔고 : {{balance}}</h3>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#example",
data: {
amount: 0,
balance: 0,
},
methods: {
specialEvent: function(e) {
this.balance += 10000;
},
......
}
})
</script>
계좌 개설 버튼을 클릭하면 10000원이 잔고에 추가되지만 once 수식어로 인해 한번만 실행됨
키코드 수식어
키보드 관련 이벤트를 처리할 때 사용할 수 있는 수식어
<div id="example" v-cloak>
<p>
이름 : <input type="text" v-model="name" v-on:keyup.13="search"
placeholder="두글자 이상을 입력하세요" />
</p>
<table id="list">
<thead>
<tr>
<th>번호</th>
<th>이름</th>
<th>전화번호</th>
<th>주소</th>
</tr>
</thead>
<tbody id="contacts">
<tr v-for="contact in contactlist">
<td>{{contact.no}}</td>
<td>{{contact.name}}</td>
<td>{{contact.tel}}</td>
<td>{{contact.address}}</td>
</tr>
</tbody>
</table>
<div v-show="isProcessing === true">조회중</div>
</div>
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/2.0.3/fetch.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.auto.min.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: '#example',
data: {
name: "",
isProcessing: false,
contactlist: []
},
methods: {
search: function(e) {
var val = e.target.value;
if (val.length >= 2) {
this.fetchContacts();
} else {
this.contactlist = [];
}
},
fetchContacts: function() {
this.contactlist = [];
this.isProcessing = true;
var url = "http://sample.bmaster.kro.kr/contacts_long/search/" + this.name;
var vm = this;
fetch(url)
.then(function(response) {
return response.json()
}).then(function(json) {
vm.contactlist = json;
vm.isProcessing = false;
}).catch(function(ex) {
console.log('parsing failed', ex);
vm.contactlist = [];
vm.isProcessing = false;
})
}
}
})
</script>
if(e.keyCode == 13) { ...... } 대신 v-on:keyup.13 수식어로 엔터 이벤트를 처리
vue.js에서 제공하는 키코드 수식어 별칭
.enter | .tab | .delete | .esc |
.space | .up | .down | .left |
.right | .ctrl | .alt | .shift |
.meta |
마우스 버튼 수식어
<div id="example" v-on:contextmenu.prevent="ctxStop"
@mouseup.left="leftMouse" @mouseup.right="rightMouse">
<div>
Left Click : 왼쪽으로<br /> Right Click : 오른쪽으로
</div>
<img src="images/foot.jpg"
v-bind:style="{ position:'absolute', left: pos.left + 'px', top:pos.top +'px' }" />
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#example",
data: {
pos: {
left: 100,
top: 100
}
},
methods: {
ctxStop: function(e) {},
leftMouse: function(e) {
if (this.pos.left > 30)
this.pos.left -= 30;
console.log("Move Left!!");
},
rightMouse: function(e) {
this.pos.left += 30;
console.log("Move Right!!");
}
}
})
</script>
마우스 우측 버튼 클릭했을 때 내장 컨텍스트 메뉴가 나타나지 않도록 contextmenu.prevent 수식어 적용
스타일 정보를 적용하기 위해 v-bind:style 사용
마우스 버튼 수식어 별칭
.left | .right | .middle |