Thảo luận về repaint reflow javascript (Dành cho level 3)

Nội dung bài viết

Repaint reflow là một khái niệm liên quan đến high-performance javascript. Cũng chính vì điều này mà các thư viện như Vue, React và Reef đều triển khai theo các làm như vậy. Nói về ưu điểm thì rõ ràng nhiều, và nhược điểm hầu như không có ngoại trừ anh em lập trình phải cố gắng học thêm.

Vì sao bài viết này dành cho từ level 3 trở lên và bạn có thể xem mình đang nằm ở level nào từ 1 đến 4. Vì ở level 3 thì phải nghiêm túc chấp hành triển khai ứng dụng có hiệu suất tốt, khi viết người khác không cần phải review hay bận tâm về vấn đề bạn làm. Cảm giác giao việc cho bạn là cảm thấy an toàn. Việc chú trọng vào hiệu suất đương nhiên càng sớm càng tốt, level 1 hay 2 đều ok, nhưng giai đoạn đầu các tân binh nên rèn luyện kỹ năng về tính logic, và code. Ví dụ bạn đang ở level 1 thì có thể lập trình từ A -> B -> C ->D. Tuy dài nhưng đúng về logic là được. Sau khi phát triển thêm thì chỉ cần cố gắng làm cách nào đi một phát từ A -> D luôn. Sau đó thì mới tính chuyện về hiệu suất.

Notes: Bài viết thuộc Series - Con đường trở thành kiến trúc sư ở đó có nhiều bài viết giúp bạn khám phá hơn được nhiều kỹ năng về hiệu suất.

Tuy nhiên đầu tiên bạn cũng cần phải hiểu một quy trình kiết xuất một trang web như thế nào khi bạn nhập url vào browser, từ đó bạn sẽ biết Repaintreflow ở bước thứ mấy mà tối ưu.

Cách trình duyệt hiển thị một trang web

Đầu tiên hãy xem cách công cụ trình duyệt phân tích cú pháp và hiển thị các trang web như thế nào thông qua hình ảnh này:

Các bước để công cụ trình duyệt phân tích cú pháp và hiển thị các trang web như sau:

Bước 1 : Đầu tiên, công cụ trình duyệt bắt đầu phân tích cú pháp tài liệu HTML và chuyển đổi mỗi thẻ thành một node DOM, anh em hay gọi là tree DOM đó.

Bước 2 : Trong khi phân tích cú pháp tài liệu HTML, nó cũng sẽ phân tích cú pháp dữ liệu kiểu trong tệp CSS bên ngoài và HTML (bao gồm cả kiểu được tạo động bởi JS).

Bước 3 : Sau khi kết xuất hoàn tất, bước vào giai đoạn xử lý bố cục, tức là gán cho mỗi node DOME một tọa độ chính xác sẽ xuất hiện trên màn hình.

Bước 4 : Toàn bộ quá trình được hoàn thành dần dần. Để hiển thị nội dung trên màn hình càng sớm càng tốt, công cụ kết xuất không đợi toàn bộ tài liệu HTML được phân tích cú pháp, sau đó bắt đầu xây dựng cây kết xuất và thiết lập bố cục. Một phần nội dung được phân tích cú pháp và hiển thị cho đến khi toàn bộ trang web được hiển thị lên.

Bạn nhìn vào đó có thể không hiểu nhiều nhưng không sao chúng ta chỉ quan tâm đến bước 3 và 4. Đó là bước reflowRepaint.

repaint reflow javascript

repaint là là hiểu theo tiếng việt là sơn lại. Nghĩa là cái cổng sắt của bạn bị tróc sơn bạn có thể sử dụng repaint để sơn lại mới, do chỉ sơn lại mới thôi cho nên bạn không thêm hay bớt khung sắt gì hết. Cũng giống như trong DOM, khi repaint lại bị thay đổi, giao diện của phần tử bị thay đổi và nó xảy ra mà không làm thay đổi bố cục, chẳng hạn như thay đổi thuộc tính border, hoặc thay đổi color đương nhiên là nó sẽ không ảnh hưởng đến việc hiển thị cấu trúc dom.

Trên đó là khái niệm về repaint tiếp theo chúng ta tìm hiểu về reflow là gì?

reflow là hiểu theo tiếng việt là chỉnh sửa lại, là chúng ta làm lại khung sắt mới, thay thế một số chỗ khung không hợp lý. Mà đã làm lại khung sắt thì bắt buộc chúng ta phải sơn lại là điều rõ ràng. Giống trong DOM, khi chúng ta thêm bớt môt phần tử DOM thì nó sẽ ảnh hưởng đến việc kết xuất cấu trúc dom, điều này sẽ thay đổi chính nó và tất cả các phần tử cha (tổ tiên) của nó.

Qua hai khái niệm trên bạn cũng đã hình dung câu chuyên rồi đúng không, vì vậy nếu như bạn càng làm thao tác reflow nhiều thì đương nhiên dẫn đến giảm hiệu suất. Đúng là, càng nhiều phần tử DOM thay đổi or thêm bớt, thì ảnh hưởng càng rõ ràng. Tiếp theo chúng ta đi qua một số ví dụ.

Ví dụ repaint reflow javascript

Ví dụ tôi thường thấy một số bạn viết code như thế này.

element.style.width = '50px'; // chỉnh sửa lại
element.style.height = '90px'; // chỉnh sửa lại
element.style.border = 'solid 1px red'; // chỉnh sửa lại

Nếu như vậy các bạn sẽ làm động tác repaint 3 lần, trình phân tích cũng phải làm việc 3 lần. Do vậy cố gắng sửa đổi các thuộc tính trên kiểu phần tử càng ít càng tốt, bạn có thể làm thế này:

element.style.cssText = 'width: 50px; height: 80px; border: solid 1px red;'

Chỉ một lần duy nhất làm việc và bạn có thể đạt được mục đích.

Tiếp theo là một ví dụ về reflows, và code này cũng xuất hiện nhiều ở những bạn mới.

let list = document.querySelector('ul');
let players = ['cr7', 'm10', 'm99'];

// Add each player to the UI
for (let player of players) {
    list.innerHTML += `<li>${player}</li>`;
}

Nếu bạn rơi vào trường hợp trên thì bạn nên xem xét lại, bạn đang khiến DOM phải thay đổi đến 3 lần, dẫn đến giảm hiệu suất khi render html. Bạn có thể làm lại điều này tránh reflow nhiều lần.

let list = document.querySelector('ul');
let players = ['cr7', 'm10', 'm99'];
let items = '';

// Add each player to the items string
for (let player of players) {
    items += `<li>${player}</li>`;
}

// Update the UI
list.innerHTML += items;

Một cách tiếp cận hiệu quả hơn sẽ là tạo một chuỗi đơn từ tất cả các mục và chèn nó khi vòng lặp hoàn thành. Ok chứ?

Một số mẹo tăng hiệu suất (VanillaJS, jQuery)

Nếu bạn sử dụng document.querySelectorAll() thì nên thay đổi qua document.getElementById() đối với tìm id thì sẽ nhanh hơn. Tiếp theo nếu tìm một element thì thay vì bạn sử dụng document.getElementsByTagName('*') thì nên sử dụng document.getElementById('id').getElementsByTagName('*') sẽ tốt hơn nhiều.

nên khai báo một biến để cache DOM lại như:

var sample = document.getElementById('test')
sample.innerHTM = ...

//better than
document.getElementById('test').innerHTM = ...

Bài viết này quá rõ, không có gì để tóm lại. Nếu bạn muốn tìm hiểu nhiều hơn về bài viết về hiệu suất thì có lẽ bạn nên theo dõi Series - Con đường trở thành kiến trúc sư với nhiều bài viết có thể để bạn khám phá.

Có thể bạn đã bị missing