기본기
전 포스팅에서 말씀드렸듯이 단일 html페이지에서부터 vuejs를 연습해볼 생각이에요. 그리고 저는 Atom을 기본편집기로 사용하였고, 테스트용 브라우져는 Chrome을 사용하였어요. 아직 단일 html페이지 연습단계이기 때문에 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
를 이용해서 cdn으로 구성하셔도 Vue문법 및 빌드는 아주 잘됩니다.
Hello, Vue js
01.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
</div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<script>
var model = {
message : "Hello, Vue js "
};
new Vue({
el: '#app',
data: model
})
</script>
</html>
가장 기본적이 예제 에요. model 객체는 변수명 그대로 model 객체에요. 데이터를 가지고있지요. 그 밑에 있는 app이라는 이름을 가지는 녀석도 객체인데 Vue객체(이하 뷰객체)이자 ViewModel 객체에요. 뷰객체에 있는 el
이라는 속성은 HTML 요소(element의 약자)를 나타네요. html 파일에서 id값을 부여하는것을 결정하죠
뷰객체가 html요소와 데이터를 참조하고 , 데이터(모델)가 변경되면 뷰모델 객체는 즉시 HTML요소(뷰)에 반영 == 반응형이라는 이야기
현재 위 코드에서 View Model 에서는 단순히 데이터만 가지고 있지만 연산(Method)들도 가지고 있죠. 그 이야기는 다음에 차차 해보도록 할게요
v-text 와 v-html
02.html
v-text와 v-html을 알아봅시다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<h1 v-html="message"></h1>
</div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<script>
var model = {
message : "<h3>Hello, Vue js</h3> "
};
new Vue({
el: '#app',
data: model
})
</script>
</html>
일단 v-html이라는 디렉티브가 message라는 변수를 받아오구요. message는<h3>Hello, Vue js</h3>
이죠. 그럼 이 대로 크롬창에 띄어보면
h3태그의 속성이 적용된(글자크기가 커지고 볼드로 바뀐) Hello, Vue js가 나옵니다. 즉 h3태그를 태그로써 인식하겠다는 이야기죠
그렇다면 v-html
을 v-text
로 변경해보세요. 그러면 아마 "<"h3>Hello, Vue js</h3">"이렇게 화면에 뜰텐데 대충 느낌오시죠?("" 제외, 마크다운이 알아서 h3를 인식해버려서...) h3태그를 인식을 안하고 그냥 문자열로 받아와서 출력해줍니다.
v-html 디렉티브는 script 태그를 그대로 바인딩 하기 때문에 요즘 문제가 되는 XSS(Cross Stie Scripting)공격 등에 취약하다고 하니 꼭 필요한 경우가 아니면 그냥 v-text사용하시는게 좋다고 하네요.
v-bind
03.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<input id="a" type="text" v-bind:value="message"><br>
<img v-bind:src="imagePath" >
</div>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<script>
var model = {
message : 'v-bind!',
imagePath : "https://www.google.co.kr/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png"
};
new Vue({
el: '#app',
data: model
})
</script>
<img v-bind:src="imagePath" >
대충 느낌이 오시나요? bind가 ViewModel이 받은 데이터와 img태그의 속성(src)을 묶어주는 것이죠. 앞으로 아주 많이 쓰게될 것 같네요. 그래서 줄임표현도 있대요 v-bind:src
==> :src
로 작성해도된데요.
v-model
04.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>{{message}}</h1>
<input v-model="message">
</div>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
message: "hi data"
}
})
</script>
지금까지 위에서 사용한 디렉티브는 다 단방향 데이터 바인딩으로 적용된 것이에요. 쉽게 생각하면 데이터의 흐름이 일방적인거죠. 가끔은 양방향이 필요한 경우가 있어요. 요소에서 변경한 값들이 모델 객체에 바로 반영될 때죠. 이런 경우에는 v-model 디렉티브를 사용하면되요.
05.html //양방향 데이터 바인딩 다른 예제
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="checkbox" value="1" v-model="number">1,
<input type="checkbox" value="2" v-model="number">2,
<input type="checkbox" value="3" v-model="number">3,
<input type="checkbox" value="4" v-model="number">4,
<input type="checkbox" value="5" v-model="number">5,
</div>
<div id="app2">
선택한 숫자들 : <span v-text="number"></span>
</div>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<script>
var model = {
number : []
};
var test1 = new Vue({
el: '#app',
data: model
})
var test2 = new Vue({
el: '#app2',
data: model
})
</script>
체크박스로 숫자를 체크하면 체크된 값을 model의 number배열에 넘겨주고 해당 number를 data로 받는 test2 뷰객체와 연결된 아래의 div에서 v-text로 표시를 해주는거에요.
근데 신기한 것은 왜 뷰객체를 두개나 만들어야되는지에요. 정확한 건 아니지만 예전에 전 포스팅에서 vue js는 단방향으로 데이터 흐름을 제어한다고 했었는데 그것 때문에 뷰객체 하나(model이라는 data를 가지는)에서 값을 입력(체크)하고 해당 값을 받아오는건 안되는 것 같아요. 실제로 <div id="app2">
에서 숫자2를 빼고 app이라는 뷰객체 하나로만 하면 체크를해도 아무런 변화가 없어요. 이점을 유의해야될 것 같아요.
v-show, v-if, v-else, v-else-if 디렉티브
06.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<input id="a" type="text" v-model="number"><br>
<img v-if="number < 1000" v-bind:src="imagePath" >
</div>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<script>
var model = {
number : 1000,
imagePath : "https://www.google.co.kr/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png"
};
new Vue({
el: '#app',
data: model
})
</script>
위코드 중 v-if
를 v-show
로 바꾸고 크롬으로 돌려보면 결과는 똑같아요. 하지만 렌더링이되고 안되고의 차이가 있어요. v-if
의 경우에는 조건에 부합하지 않으면 그냥 렌더링을 하지 않아버려요. 개발자도구를 이용해서 Elements 탭을 보시면 조건에 부합하지 않을 경우 img태그가 아예없는 것을 확인할 수 있죠.
하지만 v-show
같은 경우는 조건에 부합하든 부합하지 않든 일단 렌더링을하고 img 태그의 속성중 display: none
을 추가하는 방식이에요. 즉 v-show
보다는 v-if
로 보여주고 안보여주고를 결정하는게 전체적으로 봤을 땐 효율적이라는 얘기죠. v-else
나 v-else-if
는 그냥 조건 한번씩 추가해보세요ㅋ. 그냥 조건문이니깐요.
v-for 디렉티브
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<div v-for="team in teams">
<div>랭크 : {{team.rank}}</div>
<div>팀명 : {{team.name}}</div>
<div>홈구장 : {{team.homeground}}</div>
<br>
</div>
</div>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<script>
var model = {
teams: [
{ rank: 1, name: "리버풀", homeground: "안필드"},
{ rank: 2, name: "맨유", homeground: "올드트래포트"},
{ rank: 3, name: "바르샤", homeground: "?"}
]
};
new Vue({
el: '#app',
data: model
})
</script>
모델에서 배열데이터를 지정해놓으면 그걸 받아와서 반복시키는건데요 angular랑 거의 비슷한 것 같아요. 조금 차이점은 angular에서는 :
의 의미가 타입지정인데 vue에서는 =
의미로 사용을 하네요. 후 이게 너무 적응이 잘안되네요... 배열 내용은 json타입이으로 key,value가 있어야하구요 만약 key, value값이 없으면 인덱스를 지정해주고 getItem(index)라는 메소드를 하나만들어서 값마다 호출을 해주면 되겠죠? 그게 귀찮고 json타입으로 key값을 명시해주는게 훨씬더 직관적이니 왠만하면 json타입을 사용하시는게 좋아요.
인덱스를 추가하는 방법은 v-for="(team, index) in contacts
이렇게 사용하시면 되요.
다차원배열이 아니고 1차원배열이면서 key,value값을 가질 경우
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<select>
<option v-for="(val, key) in teams" v-bind:vlaue="key">{{val}}
</option>
</select>
</div>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<script>
var model = {
"A" : "LIVERPOOL",
"B" : "MANCHESTER_UTD",
"C" : "BARCELONA"
};
new Vue({
el: '#app',
data: {
teams : model
}
})
</script>
요부분은 좀 응용하기 좋을 것 같아서 추가했어요. 보시면 model의 데이터타입이 뭔가 다르죠? 1차원배열이면서 key, value값을 가지는 것 처럼보이는데 vue에서는 이게 객체라고 하더라구요. 객체타입을 데이터로 받아올 경우에는 반드시 key, value쌍이 존재하니까 <option v-for="(val, key) in teams" v-bind:vlaue="key">{{val}}
이런식으로 사용이 가능한거죠. option뿐만아니라 img태그나 다른 태그의 속성과 같이 엮을 때 유용하게 쓰일것 같네요.
v-pre, v-once, v-cloak
<h3 v-pre>{{ message }}</h3>
- 이렇게 적을 경우에 원래 message에 해당하는 데이터가 출려이 되야되는데 그걸 막고자 즉 콧수염을 보여주고자 할 때 사용하는 거 디렉티브에요
<h3 v-once>{{ message }}</h3>
- 이렇게 적으면 만약에 input태그를 이용해서 message를 변경하면 message가 변경되어야겠지만 변경되지 않습니다. 즉 한번만 렌더링한다는 거에요.
<h3 v-cloak>{{test}}</h3>
- 만약에 한번에 대량의 데이터를 렌더링해야할 때 Vue 인스턴스가 el 옵션의 템플릿을 컴파일을 하는데 시간이 많이걸린다. 그러면 페이지에 {{test}}가 직접접으로 표현이 되는데 이걸 숨겨주는 기능이에요.
요약
- v-text: 데이터의 문자열을 그대로 받아와서 출력
- v-html: 데이터의 문자열중 html 태그와 일치할 경우 변경해서 출력(보안취약)
- v-bind: ViewModel에서 받아온 데이터를 html태그의 속성과 결합시키는 디렉티브
- v-model: 양방향으로 Model과 ViewModel사이의 데이터를 바인딩하는 디렉티브
- v-show: 조건에 부합하지 않는 경우 display:none 속성 추가(조건상관없이 렌더링o)
- v-if: 조건에 부합하지 않는 경우 렌더링을 하지 않음.(다시 조건에 부합하지 않게되면 다시 없애버림)
- v-for: 반복문
- v-pre: {{}}을 보여주고? 싶을 때, 표현해야할 때 사용
- v-once: 단 한번만 렌더링시킬때 사용 (일종의 display에서 상수같은 개념)
- v-cloak: 대량의 데이터 렌더링 시에 일시적으로 컴파일중 데이터 출력 막는 용도
'Front_End > Vue.js' 카테고리의 다른 글
05. Vue.js Dynamic CSS 적용하기 (0) | 2018.12.14 |
---|---|
04. Vue.js 스타일 적용 방법 (0) | 2017.12.26 |
03. Vue.js 초간단 Event Handling (1) | 2017.12.25 |
02. Vue.js Vue 인스턴스 옵션 and Life Cycle (0) | 2017.12.24 |
00. Vue.js 설치와 시작 (2) | 2017.12.22 |