- v-model
- 데이터 입력
- checkbox
- radio
- select
지난 장에서는 v-bind를 이용해서 HTML 태그 속성 값을 Vue로 다루는 법을 배웠습니다. 이번에는 사용자가 입력한 데이터를 Vue로 가져오는 법에 대해 다룹니다.
웹 페이지에서 사용자가 입력한 데이터(텍스트, 선택값 등등)를 Vue로 읽어오려면 v-model 디렉티브를 사용하면 됩니다. 이를 양방향 바인딩이라고도 부릅니다. Vue 관점에서 봤을 때 웹 페이지로부터 데이터를 읽어오기도 하고 반대로 웹 페이지에 데이터를 표현도 하기 때문입니다.
<태그명 v-model="프로퍼티명"></태그명>
먼저 input 태그를 이용해서 간단한 텍스트 값을 Vue로 읽어보겠습니다.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Vue.js sample</title> <link rel="stylesheet" href="style.css" > <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> </head> <body> <h2>입력한 문자열을 표시하는 예제</h2> <div id="app"> <input v-model="myName" placeholder="이름을 입력하세요"> <p>{{myName}}</p> </div> <script> new Vue({ el:"#app", data:{ myName:'' } }) </script> </body> </html> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } .menu{ background: darkslateblue; padding : 15px; border-radius: 5px; } .menu a{ color: white; padding: 20px; } </style>
짤을 보시면 아시겠지만 실시간 랜더링(?)이라서 입력하는 매 순간에 데이터가 출력됩니다.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Vue.js sample</title> <link rel="stylesheet" href="style.css" > <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> </head> <body> <h2 align="center">입력한 문장과 문자수를 표시하는 예제</h2> <div id="app"> <textarea v-model="myText"></textarea> <p>{{myText}}</p> <p>{{myText.length}}</p> </div> <script> new Vue({ el:"#app", data:{ myText:'' } }) </script> </body> </html> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } .menu{ background: darkslateblue; padding : 15px; border-radius: 5px; } .menu a{ color: white; padding: 20px; } </style>
참고로 length는 input 태그에서도 동작합니다.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Vue.js sample</title> <link rel="stylesheet" href="style.css" > <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> </head> <body> <h2 align="center">체크박스의 ON/OFF를 확인하는 예제</h2> <div id="app"> <label><input type="checkbox" v-model="myCheck"></input>체크박스의 상태는 {{myCheck}}</label> </div> <script> new Vue({ el:"#app", data:{ myCheck:false } }) </script> </body> </html> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } .menu{ background: darkslateblue; padding : 15px; border-radius: 5px; } .menu a{ color: white; padding: 20px; } </style>
체크박스 태그의 프로퍼티명은 동일하게 사용하고, Vue에서 해당 프로퍼티명을 배열로 초기화하면 됩니다.
단, value값을 통해 꼭 각 체크박스를 구분해야 합니다.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Vue.js sample</title> <link rel="stylesheet" href="style.css" > <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> </head> <body> <h2 align="center">복수 체크박스의 ON을 확인하는 예제</h2> <div id="app"> <label><input type="checkbox" v-model="myChecks" value="green"></input>green</label> <label><input type="checkbox" v-model="myChecks" value="red"></input>red</label> <label><input type="checkbox" v-model="myChecks" value="blue"></input>blue</label> <p>체크박스의 상태는 {{myChecks}}</p> </div> <script> new Vue({ el:"#app", data:{ myChecks:[] } }) </script> </body> </html> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } .menu{ background: darkslateblue; padding : 15px; border-radius: 5px; } .menu a{ color: white; padding: 20px; } </style>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Vue.js sample</title> <link rel="stylesheet" href="style.css" > <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> </head> <body> <h2 align="center">동의에 체크하면 송신 버튼이 활성화 되는 예제</h2> <div id="app"> <label><input type="checkbox" v-model="agreeStatus">동의합니다</label> <button :disabled="!agreeStatus">송신</button> </div> <script> new Vue({ el:"#app", data:{ agreeStatus:false } }) </script> </body> </html> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } .menu{ background: darkslateblue; padding : 15px; border-radius: 5px; } .menu a{ color: white; padding: 20px; } </style>
결과
라디오버튼 역시 동일한 프로퍼티명을 사용합니다.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Vue.js sample</title> <link rel="stylesheet" href="style.css" > <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> </head> <body> <h2 align="center">선택한 라디오 버튼을 표시하는 예제</h2> <div id="app"> <label><input type="radio" value="red" v-model="myPicked">red</label> <label><input type="radio" value="green" v-model="myPicked">green</label> <label><input type="radio" value="blue" v-model="myPicked">blue</label> <p>{{myPicked}}를 선택했습니다.</p> </div> <script> new Vue({ el:"#app", data:{ myPicked:'' } }) </script> </body> </html> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } .menu{ background: darkslateblue; padding : 15px; border-radius: 5px; } .menu a{ color: white; padding: 20px; } </style>
선택한 라디오 버튼에 따라 "myPicked" 값이 달라집니다.
제가 녹화 영상을 잘라서 그렇지, 처음에는 아무 버튼도 선택하지 않았기 때문에 공백이 뜹니다.ㅎ;
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Vue.js sample</title> <link rel="stylesheet" href="style.css" > <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> </head> <body> <h2 align="center">이미지 출력을 라디오버튼으로 변경하는 예제</h2> <div id="app"> <label><input type="radio" value="face1.png" v-model="myPic">face1</label> <label><input type="radio" value="face2.png" v-model="myPic">face2</label> <br> <img :src="myPic"></img> </div> <script> new Vue({ el:"#app", data:{ myPic:'' } }) </script> </body> </html> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } .menu{ background: darkslateblue; padding : 15px; border-radius: 5px; } .menu a{ color: white; padding: 20px; } </style>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Vue.js sample</title> <link rel="stylesheet" href="style.css" > <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> </head> <body> <h2 align="center">문자열이 선택한 색으로 변하는 예제</h2> <div id="app"> <select v-model="mySelect"> <option disabled value=''></option> <option>red</option> <option>green</option> <option>blue</option> <option>gray</option> </select> <p :style="{color:mySelect}">선택한 색상은 {{mySelect}} 입니다.</p> </div> <script> new Vue({ el:"#app", data:{ mySelect:'' } }) </script> </body> </html> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } .menu{ background: darkslateblue; padding : 15px; border-radius: 5px; } .menu a{ color: white; padding: 20px; } </style>
녹화한 영상을 보니 select box가 안보이네요...(원인 모름)
허공에 클릭질하는 애처럼 보이겠지만 아닙니다ㅎㅎ
- .lazy
- .number
- .trim
상당히 유용한 v-model 수식어입니다.
<input v-model.lazy="myName">
위 예제에서 봤을 때 키보드를 누를 때마다 실시간으로 값을 받아오는데,
이게 싫을 때 쓰면 됩니다.
lazy 수식어를 사용하면 Enter키를 누르거나 포커스가 다른 곳으로 이동할 때 입력 데이터를 한꺼번에 모아서 가져갑니다.
<input v-model.number="myAge"> <p>(만) {{myAge - 1}}세 입니다.</p>
number 수식어를 사용하지 않은 상태로 위 코드를 실행하면 "-1" 부분이 그냥 문자열 자체로 출력됩니다.
<input v-model.trim="myText"> <p>{{myText}}</p>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Vue.js sample</title> <link rel="stylesheet" href="style.css" > <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> </head> <body> <h2 align="center">입력폼 활용</h2> <div id="app"> <label>이름 : </label> <input v-model.lazy="myName" placeholder="이름을 입력하세요"><br> <label>좋아하는 색은 : </label><br> <input type="radio" value="red" v-model="myColor">빨강<br> <input type="radio" value="green" v-model="myColor">녹색<br> <input type="radio" value="blue" v-model="myColor">파랑색<br> <input type="radio" value="yellow" v-model="myColor">노란색<br> <input type="radio" value="gray" v-model="myColor">회색<br> <br> <p :style="{color:myColor}">내 이름은 {{myName}} 이고 좋아하는 색은 {{myColor}} 입니다.</p> </div> <script> new Vue({ el:"#app", data:{ myName:'', myColor:'' } }) </script> </body> </html> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } .menu{ background: darkslateblue; padding : 15px; border-radius: 5px; } .menu a{ color: white; padding: 20px; } </style>
움짤이 너무 많아서 그런가 작성 시점에서 너무 버벅입니다.
움짤을 줄이던지 해야겠어요..
아니면 노트북을 바꾸라는건가~?