dearbeany
[Vue] 이벤트 핸들링(v-on) | 바인딩(ref, v-bind, v-model) | 뷰 컴포넌트 본문
1. Vue Event Handling (v-on)
- event.preventDefault()
- Vue Key Modifier (keyup)
2 Vue Bindings
- ref, @refs
- Class Bindings (v-bind)
- Form Input Bindings (v-model)
3. Vue Component
- 전역 컴포넌트 Vue.Component()
- 지역컴포넌트 components
- <template> 사용 시 주의점
1. Vue Event Handling
- v-on 디렉티브를 사용하여 DOM 이벤트를 듣고 트리거 될 때 JS를 실행가능
<button @click="count+=1">클릭</button>
- 많은 이벤트 핸들러의 로직은 복잡하여 v-on 속성 값으로 작성X. method이름을 작성한다.
<button @click="greet">인사</button>
- 메소드명을 직접 바인딩 하는 대신 인라인 JS구문에 메소드를 사용하기도
<div id="app">
<button @click="greet('수빈')">인사</button>
<button @click="greet2($event, '수빈2')">인사2</button>
</div>
<script>
const app = new Vue({
el: '#app',
methods : {
greet(msg) {
alert(`Hello ${msg}`);
},
greet2(e, msg) {
alert(`Hello ${msg}`);
console.log(e);
}
},
})
</script>
event.preventDefault()
- 제출 이벤트가 페이지를 다시 로드하지 않음 (ex. submit 후 자동 새로고침 되는 걸 방지)
- 이벤트 핸들러 내부에서 event.preventDefault() 등을 호출하는 것은 보편적
- 메소드 내에서 쉽게 작업을 할 수 있지만(페이지 이동막기2), methods는 DOM의 이벤트를 처리하는 것 보다 data 처리를 위한 로직만 작업하는 것이 좋음.(페이지 이동막기3)
<div id="app">
<h2>페이지 이동</h2>
<a href="test03.html" @click="sendMsg1">페이지 이동막기1</a> <!-- 안 막아짐 -->
<a href="test03.html" @click="sendMsg2">페이지 이동막기2</a> <!-- 막아지나 메소드 내부에서 구현했음-->
<a href="test03.html" @click.prevent="sendMsg1">페이지 이동막기3</a> <!-- 막아짐. 권장 형태. 2,3은 같은 결과-->
</div>
<script>
const app = new Vue({
el: '#app',
methods : {
sendMsg1(){
alert('막아');
},
sendMsg2(e){
e.preventDefault();
alert('막아');
}
},
})
</script>
Vue Key Modifier
- Vue는 키 이벤트를 수신할 때 v-on에 대한 키 수식어를 추가할 수 있음. (keyup : 키보드를 눌렀다 뗄 때)
'전송' 버튼 클릭 대신 '엔터키' 를 치는 것만으로 전송하도록 코드를 작성해보자.
<div id="app">
<input type="text" v-model="name" placeholder="이름 입력"> <!-- 버튼을 클릭해야만 전송됨-->
<button @click="send">전송</button>
<input type="text" v-model="name" placeholder="이름 입력2" @keyup="send"> <!--아무 키나 눌렀다 떼면 전송됨-->
<input type="text" v-model="name" placeholder="이름 입력3" @keyup.13="send"> <!--엔터키 눌렀다 떼면 전송됨-->
<input type="text" v-model="name" placeholder="이름 입력4" @keyup.enter="send"> <!--엔터키 눌렀다 떼면 전송됨-->
</div>
<script>
const app = new Vue({
el: '#app',
data(){
return{
name : '',
};
},
methods : {
send(){
alert(`${this.name}`);
}
},
})
</script>
2. Vue Bindings
ref, @refs
$refs : ref 속성이 등록된 자식 컴포넌트와 DOM 엘리먼트 객체. (템플릿, computed에서 사용X)
ref : 엘리먼트 or 자식 컴포넌트에 대한 참조를 등록하는 데 사용.
<div id="app">
<input type="text" v-model="id" placeholder="검색할 ID 입력" ref="id">
<button @click="search">아이디 중복체크</button>
</div>
<script>
const app = new Vue({
el: '#app',
data(){
return{
id : '',
};
},
methods : {
search(){
if(this.id.length === 0){
alert(`아이디를 입력해주세요`);
console.log(this.$refs); // 객체가 반환됨
this.$refs.id.focus();
return;
}
alert(`아이디 중복 체크 성공`);
}
},
})
</script>
- 사용자가 아무 것도 입력하지 않고 클릭했을 때, 경고창을 띄우고 입력창을 자동 포커스 해준다
Class Bindings
- 데이터 바인딩은 엘리먼트의 클래스 목록과 인라인 스타일을 조작위해 일반적으로 사용됨.
- v-bind 를 사용, 문자열 or 객체 or 배열을 이용할 수 있음
<style>
div {
width: 200px;
height: 200px;
border : 1px solid black;
}
.active{
background-color: black;
color: white;
}
</style>
<div id="app">
<div v-bind:class="myclass">하</div>
<div :class="{active : isActive}">하</div>
<button @click="toggle">다크모드</button> <!-- 누르면 두번째 상자의 모드가 토글된다 -->
</div>
<script>
const app = new Vue({
el: '#app',
data(){
return{
myclass: {active : true},
isActive : false,
};
},
methods : {
toggle(){
this.isActive = !this.isActive;
}
},
})
</script>
Form Input Bindings
- v-model 디렉티브를 사용하여 <form><input>과 <textarea> 엘리먼트에 양방향 데이터 바인딩을 생성 가능
- 텍스트 영역의 보간( <textarea> {{ message }} <textarea> )은 양방향바인딩 X. v-model을 사용해야
<Form>태그를 이용해서 서버에 보낼 수 있는 태그는? 3개
①<Input>(안에 속성이 많은 것임) ②<textarea> ③<select>
- text와 textarea : value, input 이벤트 사용
- checkbox, radio : checked, change 이벤트 사용
- select : value, change 이벤트 사용
- v-model은 모든 form 엘리먼트의 초기 value와 checked 그리고 selected 속성을 무시함
Form : checkbox
<div id="app">
<h2>당신이 떠나고 싶은 여행지를 선택하시오</h2>
<input type="checkbox" id="seoul" v-model="checkedAreas" value="서울">
<label for="seoul">서울</label>
<input type="checkbox" id="hawaii" v-model="checkedAreas" value="하와이">
<label for="seoul">하와이</label>
<input type="checkbox" id="bangkok" v-model="checkedAreas" value="방콕">
<label for="seoul">방콕</label>
<input type="checkbox" id="sebu" v-model="checkedAreas" value="세부">
<label for="seoul">세부</label>
<input type="checkbox" id="chungju" v-model="checkedAreas" value="충주">
<label for="seoul">충주</label>
</div>
<script>
const app = new Vue({
el: '#app',
data(){
return {
checkedAreas: []
};
},
});
</script>
Form : radio
- 하나만 선택가능하다.
<div id="app">
<h2>성별을 고르시오</h2>
<input type="radio" id="man" v-model="gender" value="남자">
<label for="man">남자</label>
<input type="radio" id="woman" v-model="gender" value="여자">
<label for="woman">여자</label>
<p>나의 성별은 {{ gender }}</p>
</div>
<script>
const app = new Vue({
el: '#app',
data(){
return {
gender: '',
};
},
});
</script>
Form : select (다중)
- select box일 경우 선택된 항목의 value 속성의 값을 관리
<div id="app">
<h2>본인의 소속 캠퍼스를 선택하시오</h2>
<select v-model="selectedArea">
<option value="" disabled>선택하세요.</option>
<option value="서울캠퍼스">서울</option>
<option value="대전캠퍼스">대전</option>
<option value="광주캠퍼스">광주</option>
<option value="부울경캠퍼스">부울경</option>
<option value="구미캠퍼스">구미</option>
</select>
<div v-if="selectedArea"> <!-- 비어있으면 안 뜨도록 -->
소속 캠퍼스는 : {{ selectedArea }} 입니다.
</div>
</div>
<script>
const app = new Vue({
el: '#app',
data(){
return {
selectedArea: ''
};
},
});
</script>
- v-for을 사용하여 작성하기
<div id="app">
<h2> 선호하는 캠퍼스를 선택하시오</h2>
<select v-model="selectedArea" multiple> <!-- 다중선택 하려면 ctrl 누르고 해야함... 번거롭 -->
<option value="" disabled>선택하세요.</option>
<option v-for="area in areas" v-bind:value="area.value">
{{area.name}}
</option>
</select>
<div v-if="selectedArea"> <!-- 비어있으면 안 뜨도록 -->
소속 캠퍼스는 : {{ selectedArea }} 입니다.
</div>
</div>
<script>
const app = new Vue({
el: '#app',
data(){
return {
selectedArea: '',
areas : [
{name : '서울', value : '서울캠퍼스'},
{name : '대전', value : '대전캠퍼스'},
{name : '광주', value : '광주캠퍼스'},
{name : '부울경', value : '부울경캠퍼스'},
{name : '구미', value : '구미캠퍼스'},
]
};
},
});
</script>
3. Vue Component
- 이전엔 여러 개의 HTML파일을 가지고 있었으나, 이제는 하나의 페이지에 부품(Component)을 조립하는 방식(SPA)
- 기본 HTML 엘리먼트를 확장하여 재사용 가능한 코드를 캡슐화 하는데 도움이 됨
- 뷰컴포넌트는 뷰인스턴스이기도 함.
- 전역(부품을 어디서든 사용) / 지역(해당 인스턴스 내에서만 사용)
(1) 전역컴포넌트
- Vue.Component(tagName, options)
<div id="app">
<my-global></my-global>
<my-global></my-global>
</div>
<script>
Vue.component('MyGlobal', {
template: `<h2>전역 컴포넌트</h2>`
})
const app = new Vue({
el: '#app',
})
</script>
(2) 지역컴포넌트
- 모든 컴포넌트를 전역으로 등록할 필요X
- components 인스턴스 옵션으로 등록함으로써 다른 인스턴스/컴포넌트의 범위에서만 사용할 수 있는 컴포넌트 생성 가능
<div id="app">
<my-local></my-local>
<my-local></my-local>
</div>
<!-- app1에서 등록한 건 지역컴포넌트이므로 app2에는 별도로 등록하지 않았기 때문에 뜨지 않음 -->
<div id="app2">
<my-local></my-local>
</div>
<script>
const app = new Vue({
el: '#app',
components:{
'my-local' : {
template : `<h2>지역 컴포넌트</h2>`
}
}
})
const app2 = new Vue({
el: "#app2"
})
</script>
(3) <template> 태그를 사용하여 전역 컴포넌트 만들어보기
- DOM을 <template>으로 사용할 때, Vue는 템플릿 콘텐츠만 가져올 수 있기 때문에 HTML이 작동하는 방식에 고유한 몇 가지 제한 사항이 적용됨. ⓛdata는 함수여야 ②<template> 태그 안은 최상위 태그 1개
● 컴포넌트에서 객체 형태로 data를 사용하면?
data: {
msg : 'hello'
}
- 컴포넌트는 우리가 쓸 때마다 새롭게 만들어져야 하는데, data가 객체를 반환할 경우 동일한 객체 주소를 참조한다.
- data는 반드시 함수여야 한다. data가 객체를 공유하는 문제는 새로운 데이터 객체를 반환하여야 한다.
<div id="app">
<my-comp></my-comp>
</div>
<template id="my-temp">
<h2> {{ msg }} </h2>
</template>
<script>
Vue.component('my-comp', {
template: '#my-temp',
data() {
return {
msg : '<template>태그로 만든 컴포넌트'
};
}
})
new Vue({
el: '#app'
})
</script>
● <template>태그로 Component 만들 때 주의할 점
- 최상위 태그가 하나 있고 그 안에서만 모두 작성해야 한다
'Vue.js' 카테고리의 다른 글
[Vue] Vue Router 라우팅 | router-link와 router-view (0) | 2022.11.02 |
---|---|
[Vue] Vue Component 통신 | JS Module | Vue CLI 실행환경 구축 (0) | 2022.11.02 |
[Vue] v-bind 디렉티브로 이미지 속성 바꿔보기 (0) | 2022.11.01 |
[Vue] 라이프사이클 | 뷰 인스턴스 옵션(methods, filter, computed, watch) (0) | 2022.10.31 |
[Vue] Vue 옵션(el, data, methods) | 보간법과 디렉티브(v- once, text, bind, html, model, show, for, on) (0) | 2022.10.31 |