+34

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:

Screenshot 2024-06-03 at 10.06.41 PM.png

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>

Screenshot 2024-06-03 at 10.07.29 PM.png

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 namevalue 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:

Screenshot 2024-06-03 at 10.15.58 PM.png

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.

Screenshot 2024-06-03 at 10.17.29 PM.png

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:

Screenshot 2024-06-03 at 10.19.24 PM.png

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:

Screenshot 2024-06-03 at 10.23.10 PM.png

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:

Screenshot 2024-06-03 at 10.24.22 PM.png

Trong ví dụ trên, chỉ những phần tử có thuộc tính visibletrue 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 visibletrue, kết quả khi ta chạy lên nom cũng tương tự:

Screenshot 2024-06-03 at 10.27.08 PM.png

Đượ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ằng item.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:

Vue key (1).jpg

Ở 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ính key 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àm key, 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ững v-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

Viblo
Let's register a Viblo Account to get more interesting posts.