[VueJs] Vạch trần lỗi performance khi dùng v-for của Tèo cùng Hằng béo

— Hằng này, review code cho anh nhá. Anh đi đá cái bánh bao. Đói quá.

— Dạ, anh đi đi, để em review. Lên mua cho em cái bánh mì hai trứng, ít rau, nhiều thịt. À, ít ớt thôi không béo nha anh.

— Vkl, tao lạy mày. Ăn như lợn vậy

20′ sau

— Anh Tèo, em thấy đoạn này chưa ổn lắm. Anh code dâm thế này thì chết.

TL; DR

  • Hạn chế đặt key của v-for là index, vì khi index thay đổi, vue sẽ render lại phần tử bị thay đổi index

Chém

— Hả. Như nào, như nào. Nói nghe coi

— Đây, anh nhìn lại code của anh này

(Bạn đọc có thể click vào đây để xem demo thực tế)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Demo render danh sách trong Vue</title>
</head>
<body>
<div id="app">
<h2>Thêm ca sĩ</h2>
<input type="text" v-model="singer">
<button @click="addSinger">Thêm</button>
<hr>
<h2>Danh sách ca sĩ</h2>
<ul>
<li v-for="(item, index) in singers" :key="index"> {{ item }}</li>
</ul>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
new Vue({
el: '#app',
data: {
singers: ["Binz", "Sơn Tùng M-TP", "Đen Vâu"],
singer: '',
index: 0,
},
methods: {
addSinger() {
if (this.singer.length === 0) {
alert('Nhập tên ca sĩ đi pa')
return
}
if (this.singers.includes(this.singer)) {
alert('Ca sĩ này đã tồn tại rồi pa')
return
}
this.singers.unshift(this.singer)
this.singer = ''
}
}
});
</script>
</body>
</html>
view raw teo_example.html hosted with ❤ by GitHub

— Ủa có gì lạ đâu? Anh cần in danh sách ra thì anh dùng v-for. Chứ không lẽ dùng gì?

— Anh dùng v-for là đúng. Nhưng mảng của anh có tính chất thay đổi (do có action thêm/sửa/xoá trên mảng), nếu anh dùng key là index của phần tử thì khi có thay đổi vue sẽ render lại toàn bộ các phần tử, kể từ phần tử bị thay đổi cho tới cuối mảng.

— Thế à. Nói mồm ai tin. Cho một ví dụ gợi cảm xem nào?

— Đây. Ví dụ còn nóng, lúc sáng em vừa đọc quyển “Vuejs – Up and Running” đây

(Bạn đọc có thể click vào đây để xem thực tế)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Demo render component trong Vue</title>
</head>
<body>
<div id="app">
<div class="floatdiv">
<h2>V-for không có key</h2>
<color-item v-for="(item, i) in items" @click.native="items.splice(i, 1)">
{{ item }}
</color-item>
</div>
<div class="floatdiv">
<h2>V-for có key</h2>
<color-item v-for="(item, i) in items1" @click.native="items1.splice(i, 1)"
:key="item">
{{ item }}
</color-item>
</div>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
const randomColor = () => `hsl(${Math.floor(Math.random() * 360)}, 75%, 85%)`;
Vue.component('color-item', {
template: '<p :style="{ backgroundColor: color, padding: `10px` }"><slot></slot></p>',
data: () => ({
color: randomColor()
})
});
new Vue({
el: '#app',
data() {
return {
items1: ['one', 'two', 'three', 'four', 'five'],
items: ['one', 'two', 'three', 'four', 'five']
}
}
})
</script>
<style>
.floatdiv {
float: left;
width: 40%;
margin: 5px;
border: 1px solid black;
}
</style>
</body>
</html>
view raw hang_example.html hosted with ❤ by GitHub

— Trong ví dụ trên, em có tạo 1 component tên là color-item. Khi component được tạo ra, sẽ random ra 1 màu làm background.

— Ừ. Thì?

— Em gán sự kiện click cho các color-item. Khi click vào thì sẽ xoá phần tử đó đi. Anh để ý sẽ thấy: khi click vào 1 phần tử ở giữa, anh sẽ thấy các phần tử kể từ phần tử anh click tới phần tử cuối cùng cũng đổi màu theo.

— Ủa đổi thật này . Hm.. Vì sao vậy nhỉ?

— Đơn giản thôi. Vì Vue dựa vào key để kiểm tra phần tử có thay đổi không. Nếu thay đổi thì sẽ render lại.

— Ủa tao có thay đổi gì những thằng đang có đâu?

— Anh dốt thế. Anh đang lấy vị trí làm key => khi anh thêm/xoá phần tử ở giữa, thì vị trí của tất cả các phần tử từ phần tử anh update đều bị thay đổi => key thay đổi còn gì nữa.

— Ờ nhể. Thế giờ anh phải nàm thao thì mới thoả mãn được Hằng đây?

— Anh lấy em … à nhầm lấy thuộc tính khác làm key thôi. Như ví dụ trên thì có thể lấy luôn item làm key, vì nó là string rồi.

— Ủa, ví dụ tao lấy cả object làm key cho củ chắc thì có sao không?

— Không sao. Nhưng nó không phải best practice. Key chỉ nên là primitive type như: int, string, bool thôi.

— Thế à :v May quá, có cao thủ review cho.

— À bánh mì bao tiền đấy anh.

— Thôi anh mời. Cảm ơn nhá

Một suy nghĩ 2 thoughts on “[VueJs] Vạch trần lỗi performance khi dùng v-for của Tèo cùng Hằng béo

Trả lời

Điền thông tin vào ô dưới đây hoặc nhấn vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Đăng xuất /  Thay đổi )

Google photo

Bạn đang bình luận bằng tài khoản Google Đăng xuất /  Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Đăng xuất /  Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Đăng xuất /  Thay đổi )

Connecting to %s