Gần đây, tôi đã phát hiện ra một vấn đề khá thú vị liên quan đến việc sử dụng key trong vòng lặp của Vue. Hãy cùng tìm hiểu và giải quyết vấn đề này nhé!
Vấn đề với việc sử dụng key
Khi sử dụng vòng lặp với v-for
trong Vue, chúng ta thường cần thêm một key để giúp Vue xác định các phần tử và cập nhật chúng một cách đúng đắn. Tuy nhiên, việc sử dụng key không đúng cách có thể gây ra những vấn đề không mong muốn.
!Sử dụng key đúng cách trong vòng lặp Vue
Ví dụ về vấn đề
Để minh họa vấn đề, hãy xem xét một ví dụ đơn giản về sử dụng v-for
trong Vue:
{{ item }}
Khi chạy mã này và nhấp vào nút "reserve", bạn sẽ thấy mảng được đảo ngược và hiển thị chính xác trên giao diện người dùng. Tuy nhiên, nếu bạn kiểm tra mã nguồn HTML, bạn sẽ nhận thấy rằng các phần tử
không bị đảo ngược vị trí, chỉ giá trị bên trong thay đổi.
Vì sao lại như vậy?
Lý do cho vấn đề này có thể được tìm thấy trong tài liệu của Vue:
Khi Vue cập nhật một danh sách các phần tử được hiển thị với
v-for
, mặc định nó sử dụng chiến lược "in-place patch". Nếu thứ tự của các phần tử đã thay đổi, thay vì di chuyển các phần tử DOM để phù hợp với thứ tự của các phần tử, Vue sẽ cập nhật từng phần tử ngay tại chỗ và đảm bảo nó phản ánh đúng giá trị nên được hiển thị ở chỉ mục đó. Điều này tương tự với hành vi củatrack-by="$index"
trong Vue 1.x.
Điều này có nghĩa là Vue không di chuyển các phần tử DOM khi thứ tự của chúng thay đổi, thay vào đó, nó chỉ cập nhật từng phần tử ngay tại chỗ để phản ánh giá trị mới. Điều này có thể gây ra những vấn đề không mong muốn, đặc biệt là khi bạn làm việc với các form.
Giải pháp
Để giải quyết vấn đề này, chúng ta cần thêm key vào vòng lặp v-for
. Hãy xem lại đoạn mã trước đây và sửa lại một chút:
Rất đáng tiếc là chỉ sử dụng index trong trường hợp này không hiệu quả, vì khi bạn đảo ngược các phần tử trong mảng, index vẫn được render theo thứ tự ban đầu. Vì vậy, chúng ta cần một khóa duy nhất và có giá trị nguyên thủy. Trong hầu hết các trường hợp, việc sử dụng index làm key không có hiệu quả, do đó tôi khuyên bạn nên xem xét việc sử dụng index khi bạn làm việc với key.
Với ví dụ đơn giản như trên, bạn có thể sử dụng giá trị của phần tử làm key (đảm bảo không có phần tử nào trùng lặp). Trong trường hợp mảng chứa các đối tượng, bạn có thể sử dụng thư viện object-hash kết hợp với các computed để tạo key cho từng phần tử. Nếu các phần tử có khóa trùng lặp, hãy tạo một key duy nhất cho mỗi phần tử bằng cách sử dụng thuật toán ngẫu nhiên.
Đây là một ví dụ khác để giúp bạn hiểu rõ hơn về vấn đề này. Đầu tiên, tôi sẽ tạo một component mới - CustomInput:
{{ title }}
Sau đó, tôi sẽ chỉnh sửa đoạn mã ban đầu về vòng lặp:
Hãy thử nhập một số thông tin và nhấp nút "reserve". Bạn sẽ thấy rằng tiêu đề của input đã thay đổi, nhưng giá trị không khớp. Điều này xảy ra vì các component không được sắp xếp lại, chỉ giá trị được cập nhật.
Để các component có thể được sắp xếp lại theo thứ tự mới, chúng ta cần thêm key vào mỗi phần tử trong vòng lặp.