Front-end/Vue.js
[Vue.js] 데이터 바인딩 Data Binding
ImYena
2021. 11. 9. 21:43
728x90
데이터 바인딩(Data Binding)
단방향 바인딩(One-way binding)
- 컴포넌트의 데이터가 변경되면 UI요소 내용 변경
양방향 바인딩(two-way binding)
- 컴포넌트의 데이터 변경 ↔ UI 요소의 변경
- 주로 폼 데이터와 폼 양식 간의 바인딩
콧수염 표현식 데이터 바인딩(Mustache Data Binding)
{{...}}
- {{ 데이터 객체 속성명 }} : {{data}}
- {{ 삼항연산식 }} : {{(data>0)?"Yes":"No"}}
- {{ 하나의 값을 산출하는 연산식 }} : {{data+1}}
- {{ 하나의 값을 리턴하는 메소드 호출 }} : {{getMethod()}}
- {{ computed 속성명 }} : {{getMethod}}
디렉티브 데이터 바인딩(Directive Data Binding)
API — Vue.js
Vue.js - The Progressive JavaScript Framework
vuejs.org
v-*="..."
- 태그 내부 속성으로 작성
Directives | |
v-text, {{ }} |
▪ 문자열 그대로 출력 ▪ <태그>{{...}}</태그>와 동일 |
v-html | ▪ 문자열 안에 HTML태그가 포함되어 있을 경우 문자로 인식하는 것이 아닌 태그 그대로 인식 ▪ 임의의 HTML을 동적으로 렌더링하는 것으로 XSS 공격에 취약함으로 사용 자제 ▪ 해당 디렉티브 안에 HTML은 <style scoped>의 스타일이 적용되지 않음으로 <style>과 같은 전역 요소 사용해야 함 |
v-show | ▪ 요소 숨김 여부 ▪ v-if와 다르게 보이지만 않을 뿐 항상 렌더링되어 DOM에 남아있음 |
v-if | ▪ 요소 제거 여부 ▪ 조건문 ▪ v-show와 다른게 조건부로 렌더링 |
v-else | ▪ v-if나 v-else-if와 함께 사용 |
v-else-if | ▪ v-if와 함께 사용 |
v-for | ▪ 반복문 |
v-bind, : |
▪ 하나 이상의 attrivutes 또는 prop을 바인딩 ▪ 속성 값 데이터 바인딩, 속성의 값으로 바인딩하기 위해서는 {{..}} 표현식 사용 불가능 |
v-model | ▪ 양방향 바인딩 ▪ Form 입력 데이터 바인딩 ▪ <input>, <select>, <textarea>, components에 한해 한정 ▪ .number을 통해 숫자(문자)를 자로 변경 |
v-once | ▪ 요소와 컴포넌트를 한 번만 렌더링, 이후 렌더링은 건너뜀 ▪ 정적 요소 |
디렉티브 사용 예시
v-for
<태그 v-for="(item, index) in 배열" :key="식별값|index">...</태그>
<태그 v-for="(val, key) in 객체" :key="식별값|index">...</태그>
<태그 v-for="(val, name, index) in 객체" :key="식별값|index">...</태그>
- index는 자동 생성되는 index
- 객체(key-value)에 대한 val은 value, key와 name은 key를 의미함
<태그 v-for="n in 10" :key="n">...</태그>
- "n in 10"은 1부터 10까지 반복하는 반복문
*JS는 in 객체, of 배열 / 뷰는 in, of 상관x
v-bind, :
<img v-bind:src="require(`@/assets/photos/${image}`)" height="300px" />
<img :src="require(`@/assets/photos/${image}`)" height="300px" />
- @ 사용을 위해서는 require()와 백틱(`) 사용 필수
<p :class="className">아름다운 풍경</p>
<p :style="css">아름다운 풍경</p>
- class나 style 속성의 속성값을 바인딩으로 주는 경우
<script>
export default {
name:"AttrBinding",
data() {
return {
image: "photo1.jpg",
className: "className",
css: "color: blue;"
};
}
}
</script>
<style scoped>
.className {color: green}
</style>
v-model
<template>
<div class="card">
<div class="card-header">
FormBinding
</div>
<div class="card-body">
<form v-on:submit.prevent="handleSubmit">
<div class="form-group row">
<label class="col-sm-2 col-form-label">Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" v-model="product.name" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Company</label>
<div class="col-sm-10">
<input type="text" class="form-control" v-model="product.company" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Price</label>
<div class="col-sm-10">
<input type="text" class="form-control" v-model.number="product.price" />
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Info</label>
<div class="col-sm-10">
<textarea class="form-control" v-model="product.info"></textarea>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Madein</label>
<div class="col-sm-10">
<select class="form-control" v-model="product.madein">
<option value="한국">한국</option>
<option value="미국">미국</option>
<option value="독일">독일</option>
</select>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Colors</label>
<div class="col-sm-10">
<div class="form-check">
<input type="checkbox" class="form-check-input" v-model="product.colors" value="black" />
<label class="form-check-label">Black</label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" v-model="product.colors" value="white" />
<label class="form-check-label">White</label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" v-model="product.colors" value="red" />
<label class="form-check-label">Red</label>
</div>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Sale1</label>
<div class="col-sm-10">
<div class="form-check">
<input type="checkbox" class="form-check-input" v-model="product.sale1" />
<label class="form-check-label">판매여부</label>
</div>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Sale2</label>
<div class="col-sm-10">
<div class="form-check">
<input type="checkbox" class="form-check-input" v-model="product.sale2" true-value="yes" false-value="no" />
<label class="form-check-label">판매여부</label>
</div>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Sex</label>
<div class="col-sm-10">
<div class="form-check">
<input type="radio" class="form-check-input" v-model="product.sex" value="man" />
<label class="form-check-label">Man</label>
</div>
<div class="form-check">
<input type="radio" class="form-check-input" v-model="product.sex" value="woman" />
<label class="form-check-label">Woman</label>
</div>
</div>
</div>
<div>
<button class="btn btn-info btn-sm mr-2" v-bind:disabled="disabledRegButton">등록</button>
</div>
</form>
</div>
</div>
</template>
- <form v-on:submit.prevent="handleSubmit"> .prevent 필수! 아니면 SPA 위반
<script>
export default {
name:"FormBinding",
data() {
return {
product: {
name: "홍길동",
company: "",
price: 0,
colors: [],
info: "",
madein: "한국",
sale1: false,
sale2: "no",
sex: "woman"
}
};
},
computed: {
disabledRegButton() {
var result = this.product.name === "" || this.product.company === "";
return result;
}
}
}
</script>
728x90
반응형