데이터 바인딩 템플릿 문법

Vue js는 양방향 데이터를 지원하기 때문에 모델에서 데이터를 정의한 후 뷰와 연결하면 어느 한쪽에 변경이 일어났을 때 다른 한쪽에 자동으로 반영이 됨.

Model에서 정의한 데이터를 View에서 이중 중괄호를 이용하여 데이터 바인딩

1. 문자열 데이터 바인딩

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
    <h1> hello, {{title}}!</h1>
</template>
 
<script>
export default {
    data(){
        return{
            title:'world'
        };
    }
}
</script>
cs

2. HTML 태그 바인딩

HTML 태그를 바인딩 할 때는 문자열 바인딩처럼 이중 중괄호를 사용하면 텍스트로 인식하기 때문에 HTML로 출력되기 위해서는 "v-html" 디렉티브를 사용해야 함.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
    <div>
        <div>{{htmlString}}</div>
        <div v-html="htmlString"></div>
    </div>
</template>
 
<script>
export default {
    data(){
        return{
            htmlString:'<p style="color:red;">This is a red String</p>'
        };
    }
}
</script> 
cs

3. Form 입력 데이터 바인딩

Input type, Textarea, Select, checkbox, radio 등의 Form Element 필드는 "v-model" 디렉티브를 사용하여 양방향 데이터 바인딩을 생성할 수 있음.

  • input type="text" : HTML에서 입력받은 데이터는 value에 저장되는데, "v-model"은 내부적으로 이 value 속성을 사용하여 data와 value속성을 바인딩 시킴.
  • input type="number" : 숫자를 입력할 시에는 "v-model.number" 디렉티브를 사용할 수 있음.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
    <div>
       <input type="text" v-model="valueModel"/><br>
       <input type="number" v-model.number="numberModel"/>
    </div>
</template>
 
<script>
export default {
    data(){
        return{
            valueModel:'South Korea',
            numberModel: 38
        };
    }
}
</script>
cs
  • Textarea: Textarea 속성은 "v-model"을 사용하여 바인딩 함.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
    <div>
        <textarea v-model="message"></textarea>
    </div>
</template>
 
<script>
export default {
    data(){
        return{
            message:"텍스트 입력 창입니다."
        };
    }
}
</script>
cs
  • Select : input type=text와 동일하게 "v-model"은 내부적으로 select의 value속성을 사용하여 양방향 데이터 바인딩.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
    <div>
        <select v-model="city">
            <option value="02">서울</option>
            <option value="031">경기</option>
            <option value="064">제주</option>
        </select>
    </div>
</template>
 
<script>
export default {
    data(){
        return{
            city:"064"
        };
    }
}
</script>
cs
  • input type="checkbox" : input type=text, select와 다르게 v-model은 내부적으로 체크박스의 value속성이 아닌 checked속성을 사용하므로 value속성에 데이터 바인딩 시 "v-bind:value"를 사용함.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
    <div>
        <label><input type="checkbox" value="서울" v-model="checked">서울</label>
        <label><input type="checkbox" value="부산" v-model="checked">부산</label>
        <label><input type="checkbox" value="제주" v-model="checked">제주</label>
        <br>
        <span>체크한 지역:{{checked}}</span>
    </div>
</template>
 
<script>
export default {
    data(){
        return{
            checked:[]
        };
    }
}
</script>
cs
  • input type="radio" : 체크박스와 마찬가지로 v-model이 내부적으로 checked속성과 바인딩이 이루어지므로, value속성에 바인딩을 하려면 "v-bind:value"를 사용함.

4.  HTML 속성 바인딩

value을 제외한 HTML 객체 속성에 데이터를 바인딩 하기 위해서 "v-bind:" 디렉티브를 사용함. "v-bind"를 생략하고 ':' (콜론)으로 단독 사용할 수도 있음.

  • Img객체의 src : 제품 이미지, 사용자 프로필 사진처럼 이미지의 주소를 img객체의 src에 바인딩 할 수 있음.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
    <div>
       <img v-bind:src="imgSrc"/>
    </div>
</template>
 
<script>
export default {
    data(){
        return{
           imgSrc:"https://kr.vuejs.org/images/logo.png"
        };
    }
}
</script>
cs

 

  • 버튼 객체의 disabled : 버튼에서 disabled 속성이 true로 되어 있으면 버튼은 비활성화 되고 클릭 이벤트가 발생 되지 않음. "v-model"는 내부적으로 value 속성과 바인딩이 이루어지고 "v-bind"는  disabled속성과 바인딩이 이루어짐.

5. 클래스 바인딩

HTML에서 사용하는 방식처럼 class 속성에 클래스 명을 입력하여 사용할 수 있고, 조건에 따라 바인딩 할 경우 "v-bind:class"를 이용해서 추가적으로 정의해서 사용할 수 있음.

앞서 살펴본 HTML속성 바인딩과 다르게 클래스 바인딩은 아래와 같이 기본 클래스와 데이터 바인딩 처리를 하는 클래스를 공존해서 사용할 수 있음.

  • 배열을 사용한 클래스 바인딩
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<template>
    <div class="container" v-bind:class="[
        activeClass,errorClass]">Class Binding
    </div>
 
</template>
 
<script>
export default {
    data(){
        return{
           activeClass:'active',
           errorClass:'text-red'
        };
    }
}
</script>
<style scoped>
.container{
    width: 100%;
    height: 500px;
}
.active{
    background-color: yellow;
    font-weight:bold;
}
.text-red{
    color:red;
}
</style>
cs

  • 인라인 스타일 클래스 바인딩: 데이터를 오브젝트로 선언해서 바인딩할 수 있음.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<div v-bind:style="styleObject">인라인 스타일 바인딩</div>
</template>
<script>
export default {
data() {
  return {
     styleObject: {
       color: 'red',
       fontSize: '13px'
     }
  };
}
}
</script>  
cs

 

리스트 랜더링(v-for)

v-for 디렉티브를 사용하여 반복적으로 다중 데이터들을 처리할 수 있음. v-for="(item, index) in items 형식을 사용하며 items는 배열을 의미하고 v-for을 통해 배열을 하나씩 읽어와서 배열의 각 아이템을item으로, 배열의 현재 index를 index로 반환해 줌.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<template>
<div>
  <table>
    <thead>
      <tr>
        <th>제품명</th>
        <th>가격</th>
        <th>카테고리</th>
        <th>배송료</th>
      </tr>
    </thead>
    <tbody>
      <tr :key="i" v-for="(product,i) in productList">
        <td>{{product.product_name}}</td>
        <td>{{product.price}}</td>
        <td>{{product.category}}</td>
        <td>{{product.delivery_price}}</td>
      </tr>
    </tbody>
  </table>
</div>
</template>
<script>
export default {
 data() {
   return {
      productList: [
        {"product_name":"기계식키보드","price":25000,"category":"노트북/태블릿","delivery_price":5000},
        {"product_name":"무선마우스","price":12000,"category":"노트북/태블릿","delivery_price":5000},
        {"product_name":"아이패드","price":725000,"category":"노트북/태블릿","delivery_price":5000},
        {"product_name":"태블릿거치대","price":32000,"category":"노트북/태블릿","delivery_price":5000},
        {"product_name":"무선충전기","price":42000,"category":"노트북/태블릿","delivery_price":5000}
      ]
   };
 }
}
</script>
<style scoped>
table {
  font-family: arial, sans-serif;
  border-collapse: collapse;
  width: 50%;
}
td, th {
  border: 1px solid #dddddd;
  text-align: left;
  padding: 8px;
}
</style>
cs

조건부 랜더링

Vue 컴포넌트에서 조건에 따라 랜더링을 하는 방법은 v-if 디렉티브와 v-show 디렉티브를 사용하는 방법이 있음.

  • v-if
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div>
 <h1 v-if="type=='A'">A</h1>
 <h1 v-else-if="type=='B'">B</h1>
 <h1 v-else>C</h1>
</div>
</template>
<script>
export default {
 data() {
   return {
     type: 'A'
   };
 }
}
</script>
cs
  • v-show: v-if 대신에 v-show를 사용하면 되고 else if, else는 지원 하지 않음
  • v-if와 v-show의 차이점
    • v-if는 조건을 만족하면 그 순간에 html 블록이 생성되고, 조건에 만족하지 않으면 html블록은 삭제됨.
    • v-show는 조건 만족 여부에 상관없이 무조건 랜더링 되어 DOM에 남아있게 됨. 조건 만족 시 css의 display CSS속성을 이용해 화면에 보여지고, 조건을 만족하지 않으면 화면에서 숨기도록 처리됨.
    • html 블록이 화면 내에서 자주 toggle되면 v-show를 사용하고, toggle이 일어나는 빈도가 적으면 v-if를 사용하는 것이 좋음.

이벤트 처리

  • 클릭 이벤트: vue컴포넌트에서 이벤트를 처리할 때 "v-on" 디렉티브를 사용하고, "v-on:"을 '@'로 대체할 수 있음. 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div>
 <button type="button" @click="increaseCounter">Add 1</button>
 <p>The counter is : {{counter}} </p>
</div>
</template>
<script>
export default {
 data() {
   return {
     counter: 0
   };
 },
 methods: {
   increaseCounter(){
     this.counter = this.counter + 1;
   }
 }
}
</script>
cs

  • Change 이벤트: select속성에서 자주 사용되며 사용자가 select에서 옵션을 바꿀 때 마다 change이벤트가 발생.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<select v-model="selectedValue" @change="changeSelect">
   <option value="서울">서울</option>
   <option value="부산">부산</option>
   <option value="제주">제주</option>
 </select>
</template>
<script>
export default {
 data() {
   return {
     selectedValue: ''
   };
  },
  methods: {
    changeSelect(){
      alert(this.selectedValue);
    }
  }
}
cs
 

Computed와 Watch

Computed와 Watch 둘 다 Vue 인스턴스 내의 정의된 데이터 값에 변경이 일어나는지를 감시하고 , 변경될 때 마다 정의된 함수가 실행되는 속성

  • Computed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<h1>Full Name:{{fullName}}</h1>
</template>
<script>
export default {
 data() {
   return {
     firstName:'JeongHwan',
     lastName:'Kim'
   };
  },
  computed: {
    fullName(){
        return this.firstName+' '+this.lastName;
    }
    }
  }
 
</script>
cs

 

Computed는 Vue 인스턴스 내에 정의된 데이터 값과 연관된 새 데이터를 정의해서 사용할 수 있도록 해줌.

위 코드에서 함수 이름인 fullName은 함수이자 동시에 Vue 인스턴스의 데이터(새로 정의된)를 의미함. fullName함수가 실행되면 데이터 fullName에 firstName과 lastName을 합친 값이 할당되고 두 값 중 하나라도 변경이 일어나면 fullName함수가 자동으로 실행되고 값이 갱신됨.

-> Computed는 함수이자 Vue 인스턴스의 데이터

  • Watch: Computed처럼 vue 인스턴스에 정의된 데이터 값에 변경이 일어나는지를 감시하고 변경이 일어나면 지정된 함수를 실행시킬 수 있는 점은 같지만 다음과 같은 차이가 있음.
  • Computed: 기존에 정의된 데이터 값을 기반으로 새로운 데이터 값을 활용하기 위해 사용됨.
  • Watch는 Watch에 정의된 데이터 값 하나만을 감시하기 위한 용도로 사용되고 Computed와 다르게 실제 데이터 변경이 일어나기 전까지 함수가 실행되지 않고 반드시 초기 값이 변경되어야 실행됨.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<template>
<div>
<h1>Full Name:{{fullName}}</h1>
<button type="button" @click="changeName">변경</button>
</div>
</template>
<script>
export default {
 data() {
   return {
     firstName:'JeongHwan',
     lastName:'Kim',
     fullName:''
   };
  },
 watch:{
   firstName(){
     this.fullName=this.firstName+this.lastName;
   },
   lastName(){
     this.fullName=this.firstName+this.lastName;
   }
 },
 methods:{
  changeName(){
    this.firstName='kevin';
  }
 }
  }
 
</script>
cs
  • firstName과 lastName의 각각의 상태변화를 감시하기 위해 watch구문에 2개의 함수를 정의.
  • 버튼 클릭 전 까지는 값에 변동이 없으므로 출력되지 않음→ changeName()함수가 실행되면(초기 firstName과 같으면 출력X) 변경 값이 출력됨.

 

+ Recent posts