Tối Ưu Hóa Trong Vue3
Bài viết này sẽ tập trung vào phiên bản mã nguồn của Vue2, trong khi Vue3 đã hoàn toàn cải tiến thuật toán Diff. Dù vậy, mục tiêu vẫn không thay đổi.
Các Tính Năng Được Cải Thiện
- Lưu trữ sự kiện: Sự kiện được lưu trữ và có thể xem như tĩnh.
- Thêm dấu hiệu tĩnh: Vue2 sử dụng Diff toàn bộ, còn Vue3 kết hợp dấu hiệu tĩnh với Diff không toàn bộ.
- Nâng cao tính tĩnh: Khi tạo nút tĩnh, nó sẽ được giữ lại và tái sử dụng sau đó.
- Sử dụng dãy con tăng dần dài nhất để tối ưu quá trình so sánh.
Lưu Trữ Sự Kiện
Xem xét một ví dụ về nút button với sự kiện click:
<button @click="xuLyClick">Nút</button>
Kết quả biên dịch trong Vue3:
export function render(_ctx, _cache) {
return (_mởKhối(), _tạoNút("button", {
onClick: _cache[0] || (_cache[0] = (...args) => (_ctx.xuLyClick && _ctx.xuLyClick(...args)))
}, "Nút"))
}
Lưu ý rằng onClick sẽ kiểm tra cache trước, nếu chưa tồn tại thì lưu vào cache. Điều này làm cho nút trở nên tĩnh, khác biệt với Vue2 không có cơ chế cache.
Dấu Hiệu Tĩnh
Dưới đây là định nghĩa các dấu hiệu tĩnh:
export const enum DauHieuTinh {
TEXT = 1,
CLASS = 2,
STYLE = 4,
THUOC_TINH = 8,
DAY_DU_THUOC_TINH = 16,
SU_KIEN = 32,
DOAN_TINH = 64,
CO_KEY_DOAN = 128,
KHONG_KEY_DOAN = 256,
CAN_PATCH = 512,
SLOT_DONG = 1024,
TINH = -1,
BAIL = -2
}
Ví dụ mã nguồn dưới đây:
<div id="ungDung">
<div>Người Dùng</div>
<p>{{ tuoi }}</p>
</div>
Biên dịch trong Vue2:
with(this){
return _tạoNút(
'div',
{attrs:{"id":"ungDung"}},
[
_tạoNút('div',[_v("Người Dùng")]),
_tạoNút('p',[_v(_s(tuoi))])
]
)
}
Trong Vue3:
const _giuNguyen_1 = { id: "ungDung" }
const _giuNguyen_2 = /*#__PURE__*/_tạoNútCon("div", null, "Người Dùng", -1 /* TINH */)
export function render(_ctx, _cache) {
return (_mởKhối(), _tạoNútCon("div", _giuNguyen_1, [
_giuNguyen_2,
_tạoNútCon("p", null, _chuyểnSangChuỗi(_ctx.tuoi), 1 /* TEXT */)
]))
}
Tăng Cường Tính Tĩnh
Ví dụ từ Vue2 và Vue3:
Vue2 mỗi lần cập nhật đều tạo mới tất cả các phần tử:
with(this){
return _tạoNút(
'div',
{attrs:{"id":"ungDung"}},
[
_tạoNút('div',[_v("Người Dùng")]),
_tạoNút('p',[_v(_s(tuoi))])
]
)
}
Trong Vue3, các phần tử không tham gia cập nhật sẽ được lưu trữ và tái sử dụng:
const _giuNguyen_1 = { id: "ungDung" }
const _giuNguyen_2 = /*#__PURE__*/_tạoNútCon("div", null, "Người Dùng", -1 /* TINH */)
Mỗi lần cập nhật chỉ cần tạo nội dung động và tái sử dụng nội dung tĩnh đã lưu trữ.
patchKeyedChildren
Trong Vue2, updateChildren thực hiện các bước:
- So sánh đầu và đầu
- So sánh cuối và cuối
- So sánh đầu và cuối
- So sánh cuối và đầu
- So sánh các phần tử còn lại
Trong Vue3, patchKeyedChildren thực hiện:
- So sánh đầu và đầu
- So sánh cuối và cuối
- Di chuyển/diễn ra/thêm dựa trên dãy con tăng dần dài nhất.
Ví dụ:
- Children cũ:
[ a, b, c, d, e, f, g ] - Children mới:
[ a, b, f, c, d, e, h, g ]
Quá trình sẽ tìm kiếm và sắp xếp theo dãy con tăng dần dài nhất để giảm thiểu việc di chuyển DOM.