ในบทความนี้เราจะมาเรียนรู้การวนลูปแสดงข้อมูลในลักษณะ List ซึ่ง Vue ก็มีเครื่องมือมาให้เราใช้งานได้อย่างง่ายดาย ก็คือ v-for มันสามารถใช้งานได้ทั้ง Array และ Object มาดูตัวอย่างแรกกันเลย
v-for กับข้อมูล Array
Template:
<ul id="example-1">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
Data:
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
จะได้ผลลัพธ์
ในตัวอย่างเราจะใช้ v-for=“item in items” ลูปแสดงผลข้อมูลที่อยู่ใน items ได้เลย นอกจากนี้เรายังสามารถดึงค่า index ของข้อมูลในแต่ละ item ออกมาได้โดยเขียนตามตัวอย่างนี้ Template:
<ul id="example-2">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
Data:
data: {
parentMessage: 'Parent',
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
ผลลัพธ์
v-for กับข้อมูล Object
v-for สามารถใช่กับ Object ได้ด้วยเหมือนกัน โดยมีรูปแบบการใช้งานดังตัวอย่างนี้ Template:
<ul id="v-for-object" class="demo">
<li v-for="value in object">
{{ value }}
</li>
</ul>
Data:
data: {
object: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
}
ผลลัพธ์
และยังสามารถดึงข้อมูลของ Key ในแต่ละ item ออกมาได้อีกด้วย ดังตัวอย่าง
<div v-for="(value, key) in object">
{{ key }}: {{ value }}
</div>
หรือ Index ของแต่ละ key ก็ยังสามารถดึงออกมาได้ ตามนตัวอย่างนี้
<div v-for="(value, key, index) in object">
{{ index }}. {{ key }}: {{ value }}
</div>
เรื่องของ Key กับ v-for
เมื่อคุณใช้งาน v-for แล้วเมื่อข้อมูลมีการเปลี่ยนแปลงลําดับใหม่ v-for จะใช้การแทนที่ของข้อมูลแทนการย้าย Dom อาจทําให้ข้อมูลอาจจะแสดงผิดพลาด เช่นข้อมูลแสดงซํ้า สิ่งที่ควรทําคือการกําหนด Key ที่ไม่ซํ้ากัน ให้กับ HTML ในแต่ละ Item เพื่อให้ Vue แยกแยะแต่ละ node ได้ มาดูตัวอย่างการใช้ Key กันครับ
<div v-for="item in items" :key="item.id">
<!-- content -->
</div>
Array Change Detection
ในกรณีที่ใช้ v-for กับ Array เราจะมาดูกันว่า การเปลี่ยนแปลงใดบ้างที่จะทําให้ v-for Render Component บ้าง
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
v-for จะไม่ Render component ใหม่ในกรณีดังต่อไปนี้
- แก้ไขข้อมูลในบาง item เช่น items[indexOfItem] = newValue
- เปลี่ยนขนาดของ Array เช่น items.length = newLength
ตามตัวอย่างนี้
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // is NOT reactive
vm.items.length = 2 // is NOT reactive
แต่เราสามารถทําแบบนี้เพื่อให้ข้อมูลอัพเดทได้
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
หรือ
// Array.prototype.splice
this.items.splice(indexOfItem, 1, newValue)
หรือ
this.$set(this.items, indexOfItem, newValue)
หรือเปลี่ยนขนาดได้โดย
this.items.splice(newLength)
Object Change Detection Caveats
ในส่วนของ Object Vue จะไม่ Detect ในกรณีที่เราเพิ่ม Key ของ Object เข้าไปตรงๆ ตามตัวอย่างนี้
var vm = new Vue({
data: {
a: 1
}
})
// `vm.a` is now reactive
vm.b = 2
// `vm.b` is NOT reactive
แต่เรายังสามารถเพิ่มได้ด้วยการใช้ set ตามตัวอย่างนี้
var vm = new Vue({
data: {
userProfile: {
name: 'Anika'
}
}
})
Vue.set(vm.userProfile, 'age', 27)
หรือ
this.$set(this.userProfile, 'age', 27)
Displaying Filtered/Sorted Results
ในบางครั้งเราต้องการแสดงผลของ List แบบเรียงลําดับ หรือมีการ Filter ข้อมูล แต่ไม่ต้องการเปลี่ยน Original Data เราสามารถใช้ Computed มาช่วยได้ตามตัวอย่างนี้ Template:
<li v-for="n in evenNumbers">{{ n }}</li>
script:
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
evenNumbers: function () {
return this.numbers.filter(function (number) {
return number % 2 === 0
})
}
}
v-for with a Range
เราสามารถกําหนดจํานวนการวนลูปแบบนี้ได้ครับ
<div>
<span v-for="n in 10">{{ n }} </span>
</div>
ผลลัพธ์
v-for with v-if
ถ้าในบางกรณีที่เราต้องการแสดงแค่บาง item เท่านั้น เราสามารถใส่เงื่อนไขเข้าไปได้เช่น
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo }}
</li>
มาถึงตอนนี้เราสามารถใช้งาน v-for ในรูแปบต่างๆกันไปแล้ว ทั้งในเรื่องของการใช้ v-for กับ Array หรือใช้ กับ Object และเงื่อนไขของการ Update ในแบบต่างๆ หวังว่าเพื่อนๆจะสามารถนําไปประยุกต์ใช้งานได้ไม่ยากครับ