จากตอนที่แล้วเราติดค้างกันในส่วนของเนื้อหาการใช้งานงาน v-for
directive มาดูกันต่อในเนื้อหาตอนนี้ ใน Vue.js, v-for เป็นคำสั่ง
directive ที่ใช้สำหรับทำ loop (วนลูป) เพื่อแสดงผลรายการของข้อมูล
ที่อยู่ใน array หรือ object ออกมาใน HTML โดยสามารถใช้ได้ใน
template ของ Vue components
ตัวอย่างการใช้ v-for กับ array:
<script setup> import { ref } from 'vue' const lists = ref(["One","Two","Three"]) const items = ref([{ message: 'Hello' }, { message: 'World' }]) </script> <template> <ul> <li v-for="item in lists"> {{ item }} </li> </ul> <ul> <li v-for="item in items"> {{ item.message }} </li> </ul> </template>
ในตัวอย่างข้างต้น:
- lists และ items คือ array ที่เราต้องการวนลูปเพื่อแสดงผล
- item คือตัวแปรที่ใช้สำหรับแทนค่าในแต่ละ iteration หรือ การทำซ้ำ ของ loop
lists จะเป็น array ของข้อมูล string ในขณะที่ items จะเป็น array ของ object
ผลลัพธ์ที่ได้
นอกจากนี้ในการใช้งาน v-for ยังสามารถรองรับการแสดงค่า index ของ แต่ละรายการได้
โดยปกติค่าจะเริ่มต้นที่ 0 โดยกำหนดเป็นค่า option ตัวที่สอง ใน วงเล็บ (item, index)
<ul> <li v-for="(item, index) in lists"> {{ item }} {{ index }} </li> </ul> <ul> <li v-for="(item, index) in items"> {{ item.message }} {{ index }} </li> </ul>
ผลลัพธ์ที่ได้
เราสามารถใช้รูปแบบการแยกทีละส่วนของตัวของ object เพื่อเข้าถึง property ของ object
นั่นๆ ได้ง่ายและสะดวกขึ้นได้ หรือที่เรียกว่า destructuring เช่น เราต้องการเข้าถึง property
ที่ชื่อว่า message เพื่อให้เรียกใช้งานได้ง่าย ก็จะใช้เป็น { message } in items ทำให้เวลา
เรียกใช้ค่า ก็ไม่ต้องใช้เป็น item.message หรือก็คือเข้าถึงการใช้ข้อมูลได้ง่ายขึ้น
<li v-for="{ message } in items"> {{ message }} </li> <!-- หรือเรียกใช้พร้อมกับกำหนด index ก็จะเป็น <li v-for="({ message }, index) in items"> {{ message }} {{ index }} </li>
กรณีใน array มีลูป array ซ้อนด้านในอีก เราสามารถเรียกใช้ v-for เพื่อลูปรายการข้อมูล
ด้านในซ้อนกันได้ ตัวอย่าง
<li v-for="item in items"> <span v-for="childItem in item.children"> {{ item.message }} {{ childItem }} </span> </li>
ตัวอย่างการใช้ Vue.js directive v-for ซ้อนกันเพื่อวนลูป (loop) ผ่านข้อมูลที่มี
โครงสร้างแบบ nested (มีรายการภายในรายการ) และแสดงผลข้อมูลเหล่านั้นในรูปแบบ HTML
ดูตัวอย่างโค้ด
<script setup> import { ref } from 'vue' const items = ref( [ { message: 'Parent 1', children: ['Child 1.1', 'Child 1.2'] }, { message: 'Parent 2', children: ['Child 2.1', 'Child 2.2'] } ] ) </script> <template> <li v-for="item in items"> <span v-for="childItem in item.children"> {{ item.message }} {{ childItem }} </span> </li> </template>
ตัวแปร items เป็นข้อมูล array ที่มี object ด้วยกัน 2 รายการ และใน property
ของแต่ละ object ก็จะมี children property ที่เป็น array ซ้อนด้านในอีกที
ผลลัพธ์ที่ได้
ตัวอย่างการใช้ v-for กับ object:
สำหรับข้อมูลประเภท object เราจะใช้ v-for สำหรับวนแสดงข้อมูล property ของ object
ทั้งหมดมาแสดง ดูตัวอย่างด้านล่างประกอบ
<script setup> import { ref, reactive } from 'vue' const myObject = reactive({ title: 'How to do lists in Vue', author: 'Jane Doe', publishedAt: '2016-04-10' }) </script> <template> <ul> <li v-for="value in myObject"> {{ value }} </li> </ul> </template>
value คือตัวแปร ที่เรากำหนดสำหรับค่าข้อมูลของ property แต่ละตัวเรียงตามลำดับ
ก็จะเป็น title author และ publishedAt หากเราต้องการชื่อ property มาใช้งาน
หรือแสดงด้วย ก็จะเป็น parameter ตัวที่ 2 ก็ให้เรากำหนดค่าเป็น key
<li v-for="(value, key) in myObject"> {{ key }}: {{ value }} </li>
ผลลัพธ์ที่ได้
นอกจากนั้นยังสามารถใช้ค่า index เป็นค่าตัวที่ 3 เพื่อนำมาใช้งานได้ ดังนี้
<li v-for="(value, key, index) in myObject"> {{ index }}. {{ key }}: {{ value }} </li>
ผลลัพธ์ที่ได้
การใช้ v-for สำหรับวนลูปตามช่วงตัวเลขหรือ Range
นอกจากเราจะใช้ v-for สำหรับข้อมูล array และ object ที่กล่าวไปแล้วข้างต้น เรายังสามารถใช้
v-for วนลูปค่าช่วงตัวเลข ตั้งแต่ 1 ถึงจำนวนที่ต้องการ (*ต้องเป็นตัวเลขจำนวนเต็ม) สมมติเช่น
เราต้องการวนลูป 10 รายการแรก ก็จะใช้เป็น
<span v-for="n in 10">{{ n }}</span>
ก็จะเป็นการวนแสดงตัวเลข 1 ถึง 10
ผลลัพธ์ทีได้
สังเกตว่า n เป็นตัวแปรหรือชื่อที่เรากำหนดใน for ได้เลย ไม่ต้องทำเป็นค่า state เราสามารถ
ใช้ชื่ออื่นใดๆ ก็ได้ โดยค่าจะเริ่มต้นที่ 1
การใช้ v-for บน <template>
รูปแบบการใช้งานคล้ายกับ v-if ที่อธิบายเพิ่มเติมในตอนที่ผานมา เพียงแต่สำหรับ v-for เป็น
การวนลูปทำซ้ำ ดังนั้น ถ้าเราต้องการคลุมส่วนของเนื้อหา ที่มีหลายๆ รายการ และต้องการ
ให้แสดงซ้ำ ก็สามารถใช้ v-for ร่วมกับ <template> ได้ ตัวอย่าง เช่น
<script setup> import { ref, reactive } from 'vue' const items = ref( [ { msg: 'Item 1' }, { msg: 'Item 2' }, { msg: 'Item 3' } ] ) </script> <template> <ul> <template v-for="item in items"> <li>{{ item.msg }}</li> <li class="divider" role="presentation"></li> </template> </ul> </template> <style scoped> .divider { border-top: 1px solid #ccc; /* เส้นแบ่งสีเทา */ margin: 10px 0;/* ระยะห่างด้านบนและด้านล่าง */ } </style>
ผลลัพธ์ที่ได้
ข้อดีของการใช้งาน <template> สำหรับ v-for ก็คือ ปกติแล้ว เมื่อมีการใช้งาน v-if และ
v-for จะไม่ใช้ทั้งสองร่วมกัน สมมติเช่น เราไม่ต้องการแสดงรายการที่ต้องทำหรือ todo list
ที่ทำเสร็จแล้ว ดูตัวอย่างประกอบ
<script setup> import { ref, reactive } from 'vue' const todos = ref( [ { name: 'Buy groceries', isComplete: false }, { name: 'Read a book', isComplete: true }, { name: 'Write a blog post', isComplete: false } ] ) </script> <template> <ul> <li v-for="todo in todos" v-if="!todo.isComplete"> {{ todo.name }} </li> </ul> </template>
ตัวอย่างโค้ดนี้จะเกิด error เพราะมีการใช้งาน v-if จะมีความสำคัญกว่า v-for จึงไม่สามารถ
ใช้ค่าจาก state ของ v-for ได้ กล่าวคือจะเข้าไปใช้ตัวแปร ที่ประกาศทีหลังไม่ได้ ดังนั้นเพื่อ
ให้ทั้งสองส่วนสามารถใช้ร่วมกันได้ เราจึงใช้ <template> กำหนดวนลูปด้านนอกด้วย v-for
และใช้ v-if ในแท็ก <li> อีกที ก็จะได้เป็น
<script setup> import { ref, reactive } from 'vue' const todos = ref( [ { name: 'Buy groceries', isComplete: false }, { name: 'Read a book', isComplete: true }, { name: 'Write a blog post', isComplete: false } ] ) const ok = ref(true) </script> <template> <ul> <template v-for="todo in todos"> <li v-if="!todo.isComplete"> {{ todo.name }} </li> </template> </ul> </template>
ผลลัพธ์ที่ได้
ก็จะแสดงเฉพาะรายการที่ยังไม่เสร็จเท่านั้น
เนื้อหาตอนนี้จะประมาณนี้ก่อน เรามาดูต่อตอนหน้า เกี่ยวกับการใช้ v-for เพิ่มเติม เมื่อข้อมูล
จำเป็นต้องจัดการ และเกิดการเปลี่ยนแปลงลำดับ และการจัดเรียง รอติดตามตอนหน้า