Bài 8: Sử dụng v-for trong VueJS
Mình đã cập nhật lại tất cả các bài với các thay đổi ở hiện tại ở năm 2024: Vue 3, Vite, Laravel 11x,...
Cập nhật gần nhất: 03/06/2024
Chào mừng các bạn quay trở lại với series học VueJS với Laravel của mình, ở bài trước mình đã hướng dẫn các bạn cách sử dụng Conditional rendering, ở bài này chúng ta sẽ cùng tìm hiểu tiếp một loại directives
nữa mà trong các dự án sẽ rất hay dùng đến đó là v-for
Trước khi bắt đầu thì đảm bảo project của các bạn đã sẵn sàng và đang chạy nha 🚀🚀
Sử Dụng v-for
Để Lặp Qua Mảng
v-for
là 1 directive mạnh mẽ cho phép chúng ta lặp qua các phần tử trong mảng và render chúng ra UI và gần như trong mọi ứng dụng ta viết sẽ đều cần dùng tới nó.
Để mở bài ta xem ví dụ sau:
<template>
<div>
<ul>
<li v-for="(item, index) in items" :key="index">{{ item }}</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue';
const items = ref(['Apple', 'Banana', 'Cherry']);
</script>
Trong ví dụ trên, chúng ta sử dụng v-for
để lặp qua mảng items
và hiển thị từng phần tử trong một danh sách <ul>
. Đừng quên thuộc tính key
để Vue có thể theo dõi các phần tử hiệu quả hơn nhé (lát nữa cuối bài mình sẽ giải thích key
dùng để làm gì nha 😉).
Khi chạy lên sẽ cho kết quả như sau:
Ta cũng có thể in ra cả index
nếu muốn:
<template>
<div>
<ul>
<li v-for="(item, index) in items" :key="index">{{ item }} - {{ index }}</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue';
const items = ref(['Apple', 'Banana', 'Cherry']);
</script>
nhìn chung cách sử dụng v-for
khá giống với những gì ta vẫn dùng khi học lập trình và sử dụng for
nhỉ, chỉ là giờ nó áp dụng trên UI 😍
v-for
Với Object
Bạn có thể sử dụng v-for
để lặp qua một mảng chứa các object và hiển thị thuộc tính của từng object.
<template>
<div>
<ul>
<li v-for="(item, index) in items" :key="item.id">
{{ index + 1 }}. {{ item.name }} - {{ item.value }}
</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue';
const items = ref([
{ id: 1, name: 'Item 1', value: 'Value 1' },
{ id: 2, name: 'Item 2', value: 'Value 2' },
{ id: 3, name: 'Item 3', value: 'Value 3' },
]);
</script>
Trong ví dụ này, chúng ta lặp qua một mảng các đối tượng items
và hiển thị các thuộc tính name
và value
của từng đối tượng trong một danh sách. Chúng ta cũng sử dụng index
để hiển thị số thứ tự của mỗi mục trong danh sách.
Nhớ sử dụng thuộc tính
key
để giúp Vue tối ưu hóa việc render lại các phần tử (nếu có)
Chạy lên sẽ cho ta kết quả như sau:
v-for
Với Range
Trong một số trường hợp ta chả có mảng gì cả, mà muốn "tàu nhanh" render một số lượng item nhất định thì ta có thể dùng Range như sau:
<template>
<div>
<ul>
<li v-for="n in 10" :key="n">Number {{ n }}</li>
</ul>
</div>
</template>
<script setup>
</script>
Đoạn mã trên sẽ tạo ra một danh sách với các số từ 1 đến 10.
Ta có thể chọn số tuỳ ý, áp dụng để render bất kì thứ gì ta muốn 😎
Sử Dụng <template>
Với v-for
(Fragment)
Khi bạn muốn render nhiều phần tử con mà không cần bọc chúng trong một phần tử cha, bạn có thể sử dụng <template>
.
<template>
<div>
<template v-for="item in items" :key="item.id">
<h3>{{ item.title }}</h3>
<p>{{ item.description }}</p>
</template>
</div>
</template>
<script setup>
import { ref } from 'vue';
const items = ref([
{ id: 1, title: 'Title 1', description: 'Description 1' },
{ id: 2, title: 'Title 2', description: 'Description 2' },
]);
</script>
Trong ví dụ này, chúng ta sử dụng <template>
để lặp qua các phần tử và render nhiều phần tử con mà không cần bọc chúng trong một phần tử cha.
"không cần bọc chúng trong một phần tử cha" tức là khi render ra DOM thật thì sẽ không có phần tử "cha" nào bọc ngoài chúng cả. Cụ thể khi chạy lên và Inspect DOM ta sẽ thấy như sau:
Như các bạn thấy thì Vue không render ra thẻ <template>
mà render trực tiếp nội dung bên trong nó
v-for
Với v-if
Khi sử dụng v-for
cùng với v-if
, ta cần phải cẩn thận với thứ tự của chúng. Vì v-for
có độ ưu tiên cao hơn v-if
.
<template>
<div>
<ul>
<li v-for="item in items" :key="item.id" v-if="item.visible">{{ item.name }}</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue';
const items = ref([
{ id: 1, name: 'Item 1', visible: true },
{ id: 2, name: 'Item 2', visible: false },
{ id: 3, name: 'Item 3', visible: true },
]);
</script>
Bởi vì v-for
có độ ưu tiên cao hơn v-if
, nên ở ví dụ trên, v-if
sẽ không có truy cập được vào item
được định nghĩa từ v-for
, và khi chạy lên ta sẽ gặp lỗi:
Ta sửa lại một chút như sau là được nhé:
<template>
<div>
<ul>
<template v-for="item in items" :key="item.id">
<li v-if="item.visible">{{ item.name }}</li>
</template>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue';
const items = ref([
{ id: 1, name: 'Item 1', visible: true },
{ id: 2, name: 'Item 2', visible: false },
{ id: 3, name: 'Item 3', visible: true },
]);
</script>
Ở trên ta tạo thẻ <template>
bọc ngoài v-if
, chạy lên như bình thường:
Trong ví dụ trên, chỉ những phần tử có thuộc tính visible
là true
mới được render
v-for
Với Component
Bạn có thể sử dụng v-for
để lặp qua và render các component.
<template>
<div>
<Item v-for="item in items" :key="item.id" :item="item" />
</div>
</template>
<script setup>
import { ref } from 'vue';
import Item from './Item.vue';
const items = ref([
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
]);
</script>
Component Item
sẽ nhận prop item
và render dựa trên dữ liệu của nó. Component kia chia như thế nào thì mình sẽ nói rõ hơn ở bài tiếp theo nhé
v-for
Với Computed Properties
Bạn có thể sử dụng computed properties
để chuẩn bị dữ liệu trước khi render với v-for
.
<template>
<div>
<ul>
<li v-for="item in filteredItems" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const items = ref([
{ id: 1, name: 'Item 1', visible: true },
{ id: 2, name: 'Item 2', visible: false },
{ id: 3, name: 'Item 3', visible: true },
]);
const filteredItems = computed(() => items.value.filter(item => item.visible));
</script>
filteredItems
là một computed property lọc ra các phần tử có thuộc tính visible
là true
, kết quả khi ta chạy lên nom cũng tương tự:
Được rồi! Dưới đây là phần key
trong v-for
với giải thích chi tiết hơn:
Thuộc Tính key
Trong v-for
🔑
Khi sử dụng v-for
trong VueJS, thuộc tính key
rất quan trọng để giúp Vue xác định và theo dõi các phần tử một cách hiệu quả. Thuộc tính key
cần có giá trị duy nhất cho mỗi phần tử trong danh sách. Điều này giúp Vue tối ưu hóa quá trình render lại các phần tử khi có thay đổi trong danh sách.
Tại Sao Cần Dùng key
?
Khi Vue render một danh sách các phần tử, nếu không có key
, Vue sẽ sử dụng chiến lược cập nhật "tối thiểu", dựa trên thứ tự của các phần tử. Điều này có thể gây ra các vấn đề sau:
- Hiệu suất kém: Vue phải so sánh từng phần tử để xác định sự khác biệt.
- Lỗi hiển thị: Khi thứ tự các phần tử thay đổi, Vue có thể không cập nhật đúng các phần tử cụ thể, dẫn đến lỗi hiển thị.
Ví Dụ Về key
Dưới đây là ví dụ về cách sử dụng key
với v-for
:
<template>
<div>
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue';
const items = ref([
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
]);
</script>
Trong ví dụ này:
key
được đặt bằngitem.id
, đảm bảo mỗi phần tử có một giá trịkey
duy nhất.key
giúp Vue biết chính xác phần tử nào thay đổi, được thêm hoặc bị xóa, từ đó tối ưu hóa quá trình render.
Ta xem hình ảnh sau:
Ở trên ta có 3 hình tròn màu đỏ, lục, lam
, trạng thái sau đó của nó là đỏ, lam, lục
. Ở đây nếu không có key
thì Vue sẽ không thể biết được là 2 hình tròn lục và lam vừa đổi chỗ cho nhau (swap) hay là hình màu lam vừa tự đổi màu thành màu lục, và màu lục tự đổi màu thành màu lam.
Và như vậy thì khi chạy thực tế, Vue sẽ "tốn công" hơn trong việc render chính xác list mà ta cần, ở một số trường hợp nó có thể bỏ hẳn cái list cũ đi và render lại từ đầu, việc này không tốt về performance, thử nghĩ nêu ta có 1000 item và phải render lại toàn bộ chỉ vì 2 phần tử thay đổi 😙
Khi Nào Nên Sử Dụng key
?
- Khi danh sách có thể thay đổi: Nếu danh sách các phần tử có thể thay đổi về nội dung hoặc thứ tự, sử dụng
key
là rất quan trọng. - Khi sử dụng
transition-group
: Khi bạn muốn áp dụng các hiệu ứng chuyển đổi cho các phần tử trong danh sách, thuộc tínhkey
giúp Vue xác định chính xác các phần tử cần áp dụng hiệu ứng.
Một Số Mẹo Khi Sử Dụng key
- Tránh sử dụng index làm
key
: Mặc dù bạn có thể sử dụng index làmkey
, nhưng điều này không được khuyến khích. Khi danh sách thay đổi, index có thể không còn duy nhất và không phản ánh đúng trạng thái của phần tử. - Sử dụng giá trị duy nhất: Đảm bảo giá trị
key
là duy nhất và không thay đổi trong suốt vòng đời của danh sách. - Chỉ nên dùng primitive types làm key: ví dụ Number, string, không dùng Object
Chú ý rằng key chỉ cần là duy nhất cho
v-for
hiện tại, không cần quan tâm tới nhữngv-for
khác có trên trang của bạn
Ta xem ví dụ sau:
<template>
<div>
<ul>
<li v-for="(item, index) in items" :key="index">
{{ item.name }}
</li>
</ul>
</div>
</template>
<script setup>
import { ref } from 'vue';
const items = ref([
{ name: 'Item 1' },
{ name: 'Item 2' },
{ name: 'Item 3' },
]);
</script>
Trong ví dụ trên, index
được sử dụng làm key
. Điều này có thể gây ra vấn đề khi danh sách thay đổi thứ tự hoặc có phần tử mới được thêm vào.
Tóm lại, thuộc tính key
trong v-for
là một công cụ mạnh mẽ giúp Vue tối ưu hóa và đảm bảo tính toàn vẹn của quá trình render. Sử dụng key
đúng cách sẽ giúp ứng dụng của ta chạy mượt mà và hiệu quả hơn.
Kết Bài
Qua bài viết này, mình hy vọng các bạn đã nắm vững cách sử dụng v-for
trong VueJS để thực hiện List Rendering
. Những kỹ thuật này sẽ giúp bạn xây dựng các ứng dụng VueJS linh hoạt và mạnh mẽ hơn.
Cảm ơn các bạn đã theo dõi, hẹn gặp lại các bạn vào những bài sau ❤️❤️
All rights reserved