v-for
디렉티브를 사용하여 배열 기반으로 리스트를 렌더링v-for
디렉티브는 item in items 형태로 특별한 문법이 필요<ul id="example-1">
<li v-for="item in items" :key="item.message">
{{ item.message }}
</li>
</ul>
<div v-for="item of items"></div>
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
v-for
블록 안에는 부모 범위 속성에 대한 모든 권한이 있음v-for
는 또한 현재 항목의 인덱스에 대한 argument 옵션(index) 을 제공<ul id="example-2">
<li v-for="(item, index) in items">
{{ index + item.message }}
</li>
</ul>
var example2 = new Vue({
el: '#example-2',
data: {
parentMessage: 'Parent',
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
v-for
디렉티브를 사용하여 객체의 속성을 반복<ul id="v-for-object" class="demo">
<li v-for="value in object">
{{ value }}
</li>
</ul>
new Vue({
el: '#v-for-object',
data: {
object: {
// value : 'How to do lists in Vue'
// name : title
// index : 0
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})
<div v-for="(value, name) in object">
{{ name + value }}
</div>
<div v-for="(value, name, index) in object">
{{ index + name + value }}
</div>
v-for
에서 렌더링된 엘리먼트 목록을 갱신할 때 기본적으로 in-place patch 전략 사용v-for
의 각 항목들에 고유한 key 속성을 제공해야 함<div v-for="item in items" v-bind:key="item.id">
<!-- content -->
</div>
push()
, pop()
, shift()
, unshift()
, splice()
, sort()
, reverse()
example1.items.push({ message: 'Baz' })
filter()
, concat()
, slice()
example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})
JavaScript의 제한으로 인해 Vue는 배열에 대해 아래와 같은 변경 사항을 감지할 수 없음
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 반응하지 않음
// 해결 방법 : Vue.set, Array.prototype.splice, vm.$set
// 컴포넌트 안에서 쓸 때 : Vue.set = this.$set
vm.items.length = 2 // 반응하지 않음
// 해결 방법 : vm.items.splice(newLength)
모던 JavaScript의 한계로 Vue는 속성 추가 및 삭제를 감지하지 못함
Vue는 이미 만들어진 인스턴스에 새로운 루트레벨의 반응형 속성을 동적으로 추가하는 것을 허용하지 않음
var vm = new Vue({
data: {
a: 1
}
})
// `vm.a`는 반응형
vm.b = 2 // 나중에 추가된 `vm.b`는 반응형 X
// 해결 방법 1. Vue.set(object, propertyName, value)
// Vue.set(vm.someObject, 'b', 2)
// 컴포넌트 안에서 쓸 때 : Vue.set = this.$set
// 해결방법 2. Object.assign()
// this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
원본 데이터를 실제로 변경하거나 재설정하지 않고 배열의 필더링 된 버전이나 정렬된 버전을 표시해야 할 때 computed
를 사용함
computed
를 사용하는 경우<li v-for="n in evenNumbers">{{ n }}</li>
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
evenNumbers: function () {
return this.numbers.filter(function (number) {
return number % 2 === 0
})
}
}
computed
를 사용할 수 없는 경우(중첩된 v-for) : methods
이용<ul v-for="set in sets">
<li v-for="n in even(set)">{{ n }}</li>
</ul>
data: {
sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
},
methods: {
even: function (numbers) {
return numbers.filter(function (number) {
return number % 2 === 0
})
}
}
v-for
with a Rangev-for
는 숫자를 사용할 수 있으며, 이 경우 템플릿을 여러 번 반복한다.
<div>
<span v-for="n in 10">{{ n }} </span>
</div>
v-for
템플릿템플릿 v-if
와 마찬가지로, <template>
태그를 사용해 여러 엘리먼트의 블럭을 렌더링한다.
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
v-for
와 v-if
v-for
와 v-if
를 동시에 사용하는 것은 추천하지 않는다.
동일한 노드에 두 가지 모두 있다면,
v-for
가 v-if
보다 높은 우선 순위를 갖는다.
즉, v-if
는 루프가 반복될 때마다 실행되며, 이는 일부 항목만 렌더링 하려는 경우 유용하다.
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo }}
</li>
<ul v-if="todos.length">
<li v-for="todo in todos">
{{ todo }}
</li>
</ul>
<p v-else>No todos left!</p>