- [개발자의품격][부트캠프][1기][18차시] Vue.js #2 | 데이터바인딩2022년 03월 05일 18시 14분 27초에 업로드 된 글입니다.작성자: DandyNow728x90반응형
데이터 바인딩
문자열
문자열 바인딩은 단방향 데이터 바인딩이다.
// src/views/DataBindingHtmlView.vue <template> <div> <div>{{ htmlString }}</div> // {{}}는 문자열을 바인딩한다. <div v-html="htmlString"></div> // v-html 디렉티브(Directive)를 사용하면 태그로 바인딩한다. </div> </template> <script> export default { components: {}, data() { return { htmlString: '<p style="color:red;">빨간색 문자</p>' } } } </script>
input
v-model을 이용하여 사용자의 입력 값, 자바스크립트 함숫값의 양방향 데이터 바인딩이 가능하다. Vue의 막강한 기능이다.
<!-- src/iews/_databinding/DataBindingInput.vue --> <template> <div> <!-- v-model 디렉티브를 이용 양방향 데이터바인딩 가능하다. --> <input type="text" name="" id="" v-model="userId" /> <button @click="myFunction">클릭</button> <button @click="changeData">변경</button> </div> </template> <script> export default { components: {}, data() { return { userId: 'jeremy' } }, methods: { myFunction() { console.log(this.userId) }, changeData() { this.userId = 'gildong' } } } </script>
input 태그에서의 v-model은 value 속성과 양방향으로 연결되어 있다. [그림 3]은 아래 코드의 실행 결과이다. 아래 코드에서 v-model.trim과 text, number 타입의 용법을 유의해서 보자!
<!-- src/views/1_databinding/DataBindingInput.vue --> <template> <div> <!-- .trim은 입력값의 앞뒤 공백을 제거해 준다. --> <input type="text" name="" id="" v-model.trim="userId" /> <button @click="myFunction">클릭</button> <button @click="changeData">변경</button> <br /> <!-- number 타입 --> <input type="number" name="" id="" v-model="num1" />+ <input type="number" name="" id="" v-model="num2" />= <span>{{ num1 + num2 }}</span> <br /> <!-- text 타입이라 문자열로 결합 --> <input type="text" name="" id="" v-model="num3" />+ <input type="text" name="" id="" v-model="num4" />= <span>{{ num3 + num4 }}</span> <br /> <!-- text 타입에서 v.model.number로 정수형으로 치환 --> <input type="text" name="" id="" v-model.number="num5" />+ <input type="text" name="" id="" v-model.number="num6" />= <span>{{ num5 + num6 }}</span> <!-- 버튼과 calculate 함수를 이용한 sum 출력 --> <!-- <input type="number" name="" id="" v-model="sum" /> --> <!-- <button @click="calculate">계산</button> --> </div> </template> <script> export default { components: {}, data() { return { userId: 'jeremy', num1: 0, num2: 0, num3: 0, num4: 0, num5: 0, num6: 0, sum: 0 } }, methods: { myFunction() { console.log(this.userId) }, changeData() { this.userId = 'gildong' }, calculate() { this.sum = this.num1 + this.num2 } } } </script>
select
select 태그에서의 v-model은 value 속성과 양방향으로 연결되어 있다.
// src/views/1_databinding/DataBindingSelectView.vue <template> <div> <select name="" id="" v-model="selectedCity"> <option value="02">서울</option> <option value="051">부산</option> <option value="064">제주</option> </select> </div> </template> <script> export default { components: {}, data() { return { // 기본값 "서울" selectedCity: '02' } } } </script>
checkbox
checkbox 타입에서 v-model은 checked 속성과 양방향으로 바인딩되어 있다. value는 이미 값이 세팅되어 있다.
<!-- src/views/1_databinding/DataBindingCheckboxView.vue --> <template> <div> <div> <!-- Vue에서는 name이 아닌 v-model로 checkbox 그룹을 만든다. --> <input type="checkbox" name="" id="html" value="HTML" v-model="favoriteLang" /> <label for="html">HTML</label> </div> <div> <input type="checkbox" name="" id="css" value="CSS" v-model="favoriteLang" /> <label for="css">CSS</label> </div> <div> <input type="checkbox" name="" id="js" value="JS" v-model="favoriteLang" /> <label for="js">JS</label> </div> <div>선택한 언어: {{ favoriteLang }}</div> </div> </template> <script> export default { components: {}, data() { return { favoriteLang: [] // checkbox는 여러 값을 선택할 수 있기 때문에 배열을 만든다. } } } </script>
[그림 5]를 통해 볼 때 Vue에서 체크박스는 체크한 순서대로 배열에 값이 담긴다. 만약 자바스크립트에서 이 같은 기능을 구현하고자 한다면 복잡한 코드가 필요하다. 사용자가 어떤 항목을 우선적으로 생각하는지에 대한 정보를 얻을 수 있다.
radio
<!-- src/views/1_databinding/DataBindingRadioView.vue --> <template> <div> <div> <input type="radio" name="" id="html" value="HTML" v-model="favoriteLang" /> <label for="html">HTML</label> </div> <div> <input type="radio" name="" id="css" value="CSS" v-model="favoriteLang" /> <label for="css">CSS</label> </div> <div> <input type="radio" name="" id="js" value="JS" v-model="favoriteLang" /> <label for="js">JS</label> </div> <div>선택한 언어: {{ favoriteLang }}</div> </div> </template> <script> export default { components: {}, data() { return { favoriteLang: 'HTML' // 값이 하나이기 때문에 문자열, 기본값 'HTML'로 설정 } } } </script>
attribute
"v-bind:"을 이용해 속성을 단방향 바인딩할 수 있다.
<!-- src/views/1_databinding/DataBindingAttributeView.vue --> <template> <div> <!-- 속성의 단방향 설정은 v-bind: 을 붙이면 된다. --> <input type="text" name="" id="" v-bind:value="userId" readonly /> <!-- v-bind는 생략 가능하며 실무에서는 생략하여 쓴다. --> <input type="text" name="" id="" :value="userId" readonly /> <br /> <!-- src 속성을 단방향으로 바인딩하였다. --> <img :src="imgSrc" alt="" style="width: 100px; height: auto" /> <br /> <!-- input:searh는 양방향 바인딩함. --> <input type="search" name="" id="" v-model="txt1" /> <!-- button은 단방향 바인딩 처리함. 단방향의 경우 "txt1 === ''"와 같은 표현식을 쓸 수 있다. --> <button :disabled="txt1 === ''">조회</button> <br /> <input type="checkbox" name="chkEmail" id="" value="" v-model="agreeEmail" /> <label for="">이메일 보내기 동의</label> <br /> <!-- v-show가 true일때 input:email을 보여준다. --> <input type="email" name="" id="" v-show="agreeEmail.length > 0" /> </div> </template> <script> export default { components: {}, data() { return { userId: 'jeremy', txt1: '', agreeEmail: [], // checkbox는 하나이더라도 배열을 선언한다. imgSrc: 'https://kr.vuejs.org/images/logo.png' } } } </script>
style
Vue에서 style은 오브젝트를 바인딩하는 것이 유리하다. 바인딩한다는 것은 프로그램적으로 변경 가능성이 있는 경우를 고려하는 것이다. 그렇지 않을 경우에는 직접 입력하면 되기 때문에 굳이 바인딩할 필요가 없다. 이런 관점에서 style과 class는 object를 바인딩하는 방식을 사용한다.
<!-- src/views/1_databinding/DataBindingStyleView.vue --> <template> <!-- div에 직접 적용 --> <div style="color: red; font-size: 30px"> 스타일 바인딩: 글씨는 red, 폰트 크기: 30px </div> <!-- 문자열 바인딩 --> <div :style="style1">스타일 바인딩: 글씨는 red, 폰트 크기: 30px</div> <!-- object 이용. 이 방식을 주로 사용한다. --> <div :style="style2">스타일 바인딩: 글씨는 red, 폰트 크기: 30px</div> <button @click="style2.color = 'blue'">색상바꾸기</button> </template> <script> export default { components: {}, data() { return { style1: 'color: red; font-size: 30px', // 문자열 바인딩이 가능하지만 특정 속성만 변경하고자 할때 어려울 수 있다. // style 바인딩은 object로 하는 것이 가장 좋다. 키는 카멜 표현식을 사용한다. style2: { color: 'red', fontSize: '30px' } } } } </script>
class
<!-- src/views/1_databinding/DataBindingClassView.vue --> <template> <div> <div :class="class1">클래스 바인딩1</div> <!-- class는 배열로 바인딩 처리 할 수 있지만 object의 불리언 값을 이용하는 것이 유리하다. 따라서 실무에서는 "클래스 바인딩2"와 같은 방식을 사용한다. --> <!-- 키가 두단어 이상일때는 ''로 묶어 줘야 한다. 한다어 일때는 그럴 필요가 없다. --> <div :class="{ active: isActive, 'text-red': hasError }"> 클래스 바인딩2 </div> </div> </template> <script> export default { components: {}, data() { return { class1: ['active', 'text-red'], // isActive가 true라서 .active가 적용된다. isActive: true, // hasError가 false라서 .text-red가 적용되지 않는다. hasError: false } } } </script> <!-- scoped 속성을 주지 않으면 global로 적용된다. 현재 vue 파일내에서만 사용하기 위해 scoped를 붙인다. --> <style scoped> .active { background-color: green; font-weight: bold; } .text-red { color: red; } </style>
list
<!-- src/views/1_databinding/DataBindingListView.vue --> <template> <div> <select name="" id=""> <option :value="city.code" :key="city.code" v-for="city in cities"> {{ city.title }} </option> </select> </div> <dir> <br /> <button @click="doSearch">조회</button> <table> <thead> <tr> <th>제품번호</th> <th>제품명</th> <th>가격</th> <th>재고</th> </tr> </thead> <tbody> <!-- <tr :key="drink.drinkId" v-for="drink in drinkList"> --> <!-- key로 삼을 유일한 값이 없을 경우 인덱스 번호 i를 넣어 줄 수 있다. --> <tr :key="i" v-for="(drink, i) in drinkList"> <td>{{ drink.drinkId }}</td> <td>{{ drink.drinkName }}</td> <td>{{ drink.price }}</td> <td>{{ drink.qty }}</td> </tr> </tbody> </table> </dir> </template> <script> export default { components: {}, data() { return { cities: [ { title: '서울', code: '02' }, { title: '부산', code: '051' }, { title: '제주', code: '064' } ], drinkList: [] } }, setup() {}, created() {}, mounted() {}, unmounted() {}, methods: { doSearch() { this.drinkList = [ { drinkId: '1', drinkName: '코카콜라', price: 700, qty: 1 }, { drinkId: '2', drinkName: '오렌지주스', price: 1200, qty: 1 }, { drinkId: '3', drinkName: '커피', price: 500, qty: 1 }, { drinkId: '4', drinkName: '물', price: 700, qty: 1 }, { drinkId: '5', drinkName: '보리차', price: 1200, qty: 1 }, { drinkId: '6', drinkName: '포카리', price: 1000, qty: 1 }, { drinkId: '7', drinkName: '뽀로로', price: 1300, qty: 1 } ] } } } </script> <style scoped> table { width: 100%; border-collapse: collapse; } tr, th, td { border: 1px solid black; border-collapse: collapse; } </style>
json-server로부터 데이터를 가져와 table을 그린다.
<template> <dir> <button @click="doSearch2">조회</button> <table> <thead> <tr> <th>Name</th> <th>Company</th> <th>Gender</th> <th>Email</th> <th>Phone</th> <th>Addres</th> </tr> </thead> <tbody> <tr :key="customer.id" v-for="customer in customerList"> <td>{{ customer.name }}</td> <td>{{ customer.company }}</td> <td>{{ customer.gender }}</td> <td>{{ customer.email }}</td> <td>{{ customer.phone }}</td> <td>{{ customer.address }}</td> </tr> </tbody> </table> </dir> </template> <script> export default { components: {}, data() { return { customerList: [] } }, methods: { async doSearch2() { const resource = 'http://localhost:3000/customers' const res = await fetch(resource) const resJson = await res.json() console.log(resJson) this.customerList = resJson } } } </script> <style scoped> table { width: 100%; border-collapse: collapse; } tr, th, td { border: 1px solid black; border-collapse: collapse; } </style>
v-for를 통해서 html 태그 안에서 for문을 돌리면서 html 요소를 핸들링할 수 있다. 양방향 데이터 바인딩이 되어 있기 때문에 다시 렌더링 하는 화면을 짤 필요 없이 데이터 변경이 일어나면 바로 반영이 된다.
<template> <dir> <table> <thead> <tr> <th>제품번호</th> <th>제품명</th> <th>가격</th> <th>주문수량</th> <th>합계</th> </tr> </thead> <tbody> <tr :key="i" v-for="(drink, i) in drinkList"> <td>{{ drink.drinkId }}</td> <td>{{ drink.drinkName }}</td> <td>{{ drink.price }}</td> <td><input type="number" v-model="drink.qty" /></td> <td>{{ drink.price * drink.qty }}</td> </tr> </tbody> </table> </dir> </template> <script> export default { components: {}, data() { return { drinkList: [ { drinkId: '1', drinkName: '코카콜라', price: 700, qty: 1 }, { drinkId: '2', drinkName: '오렌지주스', price: 1200, qty: 1 }, { drinkId: '3', drinkName: '커피', price: 500, qty: 1 }, { drinkId: '4', drinkName: '물', price: 700, qty: 1 }, { drinkId: '5', drinkName: '보리차', price: 1200, qty: 1 }, { drinkId: '6', drinkName: '포카리', price: 1000, qty: 1 }, { drinkId: '7', drinkName: '뽀로로', price: 1300, qty: 1 } ] } }, methods: {} } </script> <style scoped> table { width: 100%; border-collapse: collapse; } tr, th, td { border: 1px solid black; border-collapse: collapse; } </style>
728x90반응형'영광의 시대! > 2022 개발자의 품격 부트캠프 1기' 카테고리의 다른 글
[개발자의품격][부트캠프][1기][19차시] Vue.js #4 | extra (0) 2022.03.07 [개발자의품격][부트캠프][1기][19차시] Vue.js #3 | event (0) 2022.03.07 [개발자의품격][부트캠프][1기][17차시] Vue.js #1 | 설치, 스니핏 설정, 프로젝트 생성, 구조, 라우터 (0) 2022.03.05 [개발자의품격][부트캠프][1기][16차시] 부트스트랩 #4 | 모달 (0) 2022.03.02 [개발자의품격][부트캠프][1기][16차시] 부트스트랩 #3 | 생성 (0) 2022.03.02 다음글이 없습니다.이전글이 없습니다.댓글