OrderList1.vue
<template>
<div>
<table class="table">
<tr v-for="(item, idx) in items" v-bind:key="item.no">
<td>
<div class="form-check">
<input class="form-check-input" type="checkbox" v-bind:value="idx" id="flexCheckDefault" v-model="chks">
<label class="form-check-label" for="flexCheckDefault">{{item.no}}</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" v-bind:value="idx" id="flexCheckDefault1" v-model="chks1[idx]">
<label class="form-check-label" for="flexCheckDefault1">{{item.no}}</label>
</div>
</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>{{item.cnt}}</td>
<td>{{item.sum}}</td>
</tr>
<tr>
<td>합계</td>
<td></td>
<td>{{addPrice}}</td>
<td>{{addCnt()}}</td>
</tr>
</table>
</div>
</template>
<script>
export default {
name: 'OrderList1',
watch:{
chks: {
handler(){
for(let item of this.items){
item['sum'] = 0;
}
for(let idx of this.chks){
this.items[idx].sum = this.items[idx].price * this.items[idx].cnt;
}
}
},
chks1: {
deep: true,
handler(){
console.log(this.chks1);
for(let i = 0; i < this.chks1.length; i++){
if(this.chks1[i] === true){
this.items[i]['sum'] = this.items[i].price * this.items[i].cnt;
}else{
this.items[i]['sum'] = 0;
}
}
}
}
},
computed: {
addPrice(){
console.log('computed');
let sum = 0;
for(let tmp of this.items){
sum += tmp.price;
}
return sum;
}
},
methods: {
addCnt(){
console.log('methods');
let sum = 0;
for(let tmp of this.items){
sum += tmp.cnt;
}
return sum;
}
},
created() {
console.log('created');
const result = [
{no:1, name:'a', price:1230, cnt:2},
{no:2, name:'b', price:1240, cnt:3},
{no:3, name:'c', price:1250, cnt:4}
];
this.items = result;
for(let i = 0; i < this.items.length; i++){
this.items[i]['sum'] = 0;
this.chks1[i] = false;
}
},
mounted() {
console.log('mounted');
},
data() {
console.log('data');
return{
items: [],
chks: [],
chks1: []
}
},
}
</script>
<style scoped>
</style>
- watch의 경우 onchange와 마찬가지로 객체의 상태 변화가 일어날 때 자동으로 호출이 된다. 위 예제는 체크박스에 체크가 되면 아이템의 가격과 수량을 곱하여 테이블에 출력한다.
- chks와 chks1은 차이가 있다. 그 차이는 가변길이의 리스트와 정해진 길이의 리스트이다. chks1의 경우 item의 갯수만큼 false로 초기화를 하는 반면에 chks는 체크가 될 경우 리스트에 값이 들어오게 된다.
- chks의 경우 체크가 된 순서대로 리스트에 들어오게 되고 이는 순서를 보장할 수 없게 된다.
- 위의 문제를 해결하기 위해 chks1에는 false값을 저장하고 체크가 된 인덱스에 true값을 저장했는데 이렇게 할 경우 메모리 낭비가 발생할 수 있다는 것을 확인했다.
OrderList2.vue
<template>
<div class="container">
<table class="table">
<tr v-for="(item) in items" v-bind:key="item.no">
<td>{{item.no}}</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>
<select v-model.number="item.opt">
<option v-for="num in item.cnt" v-bind:key="num" >{{num}}</option>
</select>
</td>
<td>{{item.sum}}</td>
</tr>
</table>
</div>
</template>
<script>
export default {
name: 'OrderList2',
data(){
return{
items : [],
}
},
created(){
const result = [
{no:1, name:'a', price:1230, cnt:10},
{no:2, name:'b', price:1240, cnt:10},
{no:3, name:'c', price:1250, cnt:10}
];
this.items = result;
for(let i = 0; i < this.items.length; i++){
this.items[i]['opt'] = 1;
this.items[i]['sum'] = this.items[i]['price'] * this.items[i]['opt'];
}
},
mounted(){
},
watch : {
items:{
deep:true,
handler(){
for(let i in this.items){
this.items[i]['sum'] = this.items[i]['price'] * this.items[i]['opt'];
}
}
}
},
methods : {
}
}
</script>
<style scoped>
</style>
- 위 예제는 아이템의 갯수를 가격에 곱하여 화면에 출력하는것으로 동작방식은 동일하다.