vue.js
Vue Event
코딩 화이팅
2023. 5. 3. 14:16
Instance Life Cycle Hooks
- 각 Vue 인스턴스는 생성될 때 일련의 초기화 단계를 걸친다.
- 데이터 관찰 설정이 필요한 경우
- 템플릿을 컴파일하는 경우
- 인스턴스를 DOM에 마운트(연결)하는 경우
- 데이터가 변경되어 DOM을 업데이트 하는 경우
- 그 과정에서 사용자 정의 로직을 실행할 수 있는 Life Cycle Hooks도 호출
- 크게 4개의 파트(생성, 부착, 갱신, 소멸)로 나뉜다.
- 모든 Life Cycle Hooks는 자동으로 this 컨텍스트를 인스턴스에 바인딩하므로 데이터, 계산된 속성 및 메소드에 접근 가능(화살표 함수 사용 X)
beforeCreate / created
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<div>{{count}}</div>
<button @click="count++">증가</button>
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
count: 0,
};
},
beforeCreate() {
console.log("beforeCreate count : " + this.count);
},
created() {
console.log("created count : " + this.count);
console.log("created에 연결된 DOM : " + this.$el);
},
});
</script>
</body>
</html>

beforeMount / mounted
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<div>{{count}}</div>
<button @click="count++">증가</button>
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
count: 0,
};
},
beforeMount() {
console.log("beforeMount count : " + this.count);
console.log("beforeMount에 연결된 DOM : " + this.$el);
},
mounted() {
console.log("mounted count : " + this.count);
console.log("mounted에 연결된 DOM : " + this.$el);
},
});
</script>
</body>
</html>

beforeUpdated / updated
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<div>{{count}}</div>
<button @click="count++">증가</button>
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
count: 0,
};
},
beforeUpdate() {
console.log("beforUpdate 호출");
},
updated() {
console.log("updated 호출");
console.log("updated count : " + this.count);
},
// 파괴는 따로 하지는 않겠다.
});
</script>
</body>
</html>

처음에는 아무것도 뜨지 않았다가 값이 변경되면 위와 같이 update된 값들이 호출된다.
Vue Event Handling
Vue Listening to Event
v-on 디렉티브를 사용하여 DOM 이벤트를 듣고 트리거될 때 JavaScript를 실행할 수 있음
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<!-- 이벤트 청취 -->
<button @click="count+=1">증가</button>
<!-- v-on : @ -->
<div>{{count}}</div>
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
count: 0,
};
},
});
</script>
</body>
</html>

Vue Method Event Handler
- 많은 이벤트 핸들러의 로직은 복잡하여 v-on 속성 값으로 작성하기는 간단하지 않음
- 때문에 v-on이 호출하고자하는 method의 이름을 받는 이유
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<!-- 이벤트 메소드 처리 -->
<button @click="greet">인사</button>
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
name: "OPP",
};
},
methods: {
//event라고 하는것은 넘기지 않아도 괜찮아~~
greet(event) {
alert(`${this.name}님 하이요`);
event.target.innerText = "얍";
console.log(event);
},
},
});
</script>
</body>
</html>

처음에는 인사라는 버튼으로 시작을 하지만 인사 버튼을 누르면

메시지가 뜨고 확인을 누르면

얍이라는 버튼으로 바뀌고 이벤트들의 속성들을 볼 수 있다.
Vue Method in Inline Handlers
- 메소드 이름을 직접 바인딩 하는 대신 인라인 JavaScript 구문에 메소드를 사용할 수도 있음
- 때로 인라인 명령문 핸들러에서 원본 DOM 이벤트에 엑세스 해야할 수도 있음
$event 변수를 사용해 메소드에 전달할 수 있음
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<!-- 이벤트 메소드 인자 넘겨보기 -->
<button @click="greet1('봉준르')">인사</button>
<button @click="greet2($event, '봉준르')">인사</button>
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
name: "OPP",
};
},
methods: {
greet1(msg, e) {
alert(`${this.name}님 ${msg}`);
console.log(e);
},
//봉준르라는 msg를 넘겨받아 쓸 수 있다.msg와 e의 순서는 바뀌면 안됨.
//e라고 하는 걸 파라미터로 받았지만 지정해준게 없으니 뭔지 알 수가 없음
greet2(e, msg) {
alert(`${this.name}님 ${msg}`);
console.log(e);
},
//$event를 붙여주면 event를 받아올 수 있다.
},
});
</script>
</body>
</html>
왼쪽 인사

오른쪽 인사



Vue Event Modifier
- 이벤트 핸들러 내부에서 event.preventDefault()(기본 이벤트를 막아줌)등을 호출하는 것은 보편적인 일이다.
- 메소드 내에서는 쉽게 작업을 할 수 있지만, methods는 DOM의 이벤트를 처리하는 것보다 data 처리를 위한 로직만 작업하는 것이 좋음.
- v-on 이벤트에 이벤트 수식어를 제공
- 체이닝 가능(여러개 붙일 수 있음)
- prevent : event.preventDefault() 호출-제출 이벤트가 페이지를 다시 로드X
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<!-- 이벤트 수식어 -->
<h2>페이지이동</h2>
<a href="test03.html" @click="sendMsg">페이지 이동막기1</a><br />
<a href="test03.html" @click="sendMsg2">페이지 이동막기2</a><br />
<a href="test03.html" @click.prevent="sendMsg">페이지 이동막기3</a><br />
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
name: "OPP",
};
},
methods: {
sendMsg() {
alert("막아");
},
sendMsg2(event) {
alert("막아");
event.preventDefault();
},
},
});
</script>
</body>
</html>
1번을 누르면


페이지 이동을 해버린다. 하지만 2번과 3번을 누르면 첫번째 사진처럼 막아라는 alert창이 뜨고 그 페이지에 그대로 머물게 된다.
Vue Key Modifier
- Vue는 키 이벤트를 수신할 때 v-on에 대한 키 수식어를 추가할 수 있음
- .enter(.13)
- .tab
- .delete("Delete"와 "Backspace"키 모두 캡쳐)
- .esc
- .space
- .up / .down / .left / .right
- 전역 config.keyCodes 객체를 통해 사용자 지정 키 수식어 별칭 지정 가능
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<!-- 이벤트 키 수식어 -->
<h2>이름 검색</h2>
<input type="text" v-model="name" placeholder="이름 입력1" id="search" />
<button @click="send">전송</button><br />
이거는 전송을 눌렀을 때 alert
<input
type="text"
v-model="name"
placeholder="이름 입력2"
@keyup="send"
/><br />
입력이 끝나서 키보드가 위로 올라왔을 때 alert창이 뜬다.
<input
type="text"
v-model="name"
placeholder="이름 입력3"
@keyup.13="send"
/><br />
13은 엔터의 의미로 엔터를 치면 alert창이 뜬다.
<!-- 위 아래는 같다 -->
<input
type="text"
v-model="name"
placeholder="이름 입력3"
@keyup.enter="send"
/><br />
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
name: "OPP",
};
},
methods: {
send() {
// document.querySelector("#search").value
alert(this.name);
},
},
});
</script>
</body>
</html>

Vue Bindings
ref, $refs
- $refs : ref 속성이 등록된 자식 컴포넌트와 DOM 엘리먼트 객체
템플릿이나 계산된 속성에서 사용X - ref : 엘리먼트 또는 자식 컴포넌트에 대한 참조를 등록하는데 사용
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<!-- $refs, ref -->
<h2>이름 등록</h2>
<input type="text" v-model="name" placeholder="이름 입력" ref="name" />
<!-- 이름중복체크 -->
<button @click="check">중복쳌</button>
<button @click="send">전송</button><br />
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
name: "OPP",
};
},
methods: {
send() {
alert(`${this.name} 등록`);
},
check() {
//만약에 통과하지 못했다면 다시 input태그에 바로 작성이 가능하도록 활성화가 되면 좋겠다.
// this.name : 요걸 이용해서 우리의 back 서버로 요청을 날리겠다.
//입력을 하지 않았을 때만 판단~~ / 실제로는 서버로 요청을 날려서.. 그 여부 또한 확인해주는게 좋음
if (this.name.length === 0) {
alert("아이디를 입력해주세요.");
this.$refs.name.focus();
console.log(this.$refs);
console.log(this.$refs.name);
return;
}
alert("아이디 중복쳌 성공");
},
},
});
</script>
</body>
</html>
이름이 등록된 상태에서 중복쳌을 누르면 아래와 같은 alert가 뜬다.

아무것도 입력되지 않은 상태에서 중복쳌을 누르면 아래와 같이 alert가 뜬다.


$ref가 뭔지 출력되고, $ref.name이 출력된다. 그리고 이름 입력란이 다시 활성화가 돼 바로 입력할 수 있게 해준다.
Class Bindings
- 데이터 바인딩은 엘리먼트의 클래스 목록과 인라인 스타일을 조작하기 위해 일반적으로 사용
- 문자열 이외에 객체 또는 배열을 이용할 수 있음.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
<style>
div {
width: 200px;
height: 200px;
border: 1px solid black;
}
.dark {
background-color: black;
color: white;
}
</style>
</head>
<body>
<div id="app">
<div v-bind:class="myclass">얍</div>
<div :class="{dark: isDark}">얍</div>
isDark를 통해 dark라는 것을 true,false 만들어준다.
<button @click="toggle">다크모드전환</button>
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
myclass: {
dark: true,
// white: true,
},
isDark: false,
};
},
methods: {
toggle() {
this.isDark = !this.isDark;
isDark를 true,false를 반대로 해준다.
},
},
});
</script>
</body>
</html>

다크모드전환을 누르면 밑에 얍이 검정 흰색으로 바뀐다.
Form Input Bindings
- v-model 디렉티브를 사용하여 form input과 textarea 엘리먼트에 양방향 데이터 바인딩을 생성할 수 있음
- text와 textarea : value, input 이벤트 사용
- checkbox, radio : checked, change 이벤트 사용
- select : value, chanege 이벤트 사용
- v-model은 모든 form 엘리먼트의 초기 value와 checked 그리고 selected 속성을 무시함
Form : text, textarea
텍스트 영역의 보간 (<textarea> {{message}} </textarea>)은 작동X v-model을 사용
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<input type="text" v-model="name" placeholder="이름 입력" /> <br />
<textarea v-model.lazy="msg"></textarea><br />
v-model.lazy : 작성하고 벗어나는 순간 바뀐다.
<!-- <textarea>{{msg}}</textarea><br /> 요런식으로는 작성 x -->
<div>{{name}}님에게 보내는 메시지는 {{msg}}와 같습니다.</div>
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
name: "",
msg: "",
};
},
});
</script>
</body>
</html>

Form : checkbox
- 하나의 체크박스일 경우 boolean 값을 표현
- 여러개의 체크박스는 같은 배열을 바인딩할 수 있음
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<div>이메일 수신 동의? <input type="checkbox" v-model="email" /></div>
<div>로봇이니? <input type="checkbox" v-model="robot" true-value="Y" false-value="N" /></div>
true-value="Y" false-value="N"로 바꿔 줄 수 있다.
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
email: false,
robot: "Y",
};
},
});
</script>
</body>
</html>

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<div>
<h2>내가 가고 싶은 여행지~~ 체크해주세요.</h2>
<input type="checkbox" id="busan" v-model="checkAreas" value="부산" />
<label for="busan">부산</label>
label을 넣어서 부산이나 일본을 눌러도 체크가 되게 만들 수 있다.
<input type="checkbox" id="japan" v-model="checkAreas" value="일본" />
<label for="japan">일본</label>
<p>나는 이번에 여기를 갈거야 `~ {{checkAreas}}</p>
</div>
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
checkAreas: [],
};
},
});
</script>
</body>
</html>

Form : radio
라디오 박스일 경우 선택된 항목의 value 속성의 값을 관리
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<div>
<h2>현재 당신이 속해있는 캠퍼스를 고르세요</h2>
<input type="radio" id="seoul" v-model="campus" value="seoul" />
<label for="seoul">서울</label>
<input type="radio" id="daejeon" v-model="campus" value="daejeon" />
<label for="daejeon">대전</label>
<input type="radio" id="buk" v-model="campus" value="buk" />
<label for="buk">부울경</label>
<input type="radio" id="gumi" v-model="campus" value="gumi" />
<label for="gumi">구미</label>
<input type="radio" id="gwangju" v-model="campus" value="gwangju" />
<label for="gwangju">광주</label>
<p>나의 캠퍼스는 `~ {{campus}}</p>
</div>
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
campus: "",
};
},
});
</script>
</body>
</html>

Form : select(단일)
- select box일 경우 선택된 항목의 value 속성의 값을 관리
- v-model 표현식의 초기 값이 어떤 옵션에도 없으면 <select> 엘리먼트는 '선택없음' 상태로 렌더링
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<div>
<h2>현재 당신이 속해있는 캠퍼스를 고르세요</h2>
<select v-model="campus">
<option value="" disabled>선택하세요~</option>
<option value="seoul">서울</option>
<option value="daejeon">대전</option>
<option value="buk">부울경</option>
<option value="gumi">구미</option>
<option value="gwangju">광주</option>
</select>
<div v-if="campus">
<p>나의 캠퍼스는 {{campus}}</p>
</div>
캠퍼스가 있을 때만 보여주게 하기
</div>
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
campus: "",
};
},
});
</script>
</body>
</html>


미리 배열로 만들어놓고 만든 배열들을 반복문으로 불러오기
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<div>
<h2>지망하는 캠퍼스를 골라보세요</h2>
<select v-model="campus" name="campus">
<option v-for="area in areas" :value="area.value">{{area.name}}</option>
</select>
<div v-if="campus">
<p>나의 지망 캠퍼스는 {{campus}}</p>
</div>
</div>
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
campus: "",
areas: [
{
name: "서울",
value: "seoul",
},
{
name: "대전",
value: "daejeon",
},
{
name: "부울경",
value: "buk",
},
{
name: "구미",
value: "gumi",
},
{
name: "광주",
value: "gwangju",
},
],
};
},
});
</script>
</body>
</html>

Form : select(다중)
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<div>
<h2>지망하는 캠퍼스를 골라보세요</h2>
<select v-model="campus" multiple>
<option value="" disabled>선택하세요~</option>
<option value="seoul">서울</option>
<option value="daejeon">대전</option>
<option value="buk">부울경</option>
<option value="gumi">구미</option>
<option value="gwangju">광주</option>
</select>
<div v-if="campus">
<p>나의 지망 캠퍼스는 {{campus}}</p>
</div>
</div>
</div>
<script>
const app = new Vue({
el: "#app",
data() {
return {
campus: [],
// 배열로 바꿔줘야된다.
};
},
});
</script>
</body>
</html>
