- Bài viết bàn về việc làm chủ thao tác với Document Object Model (DOM) bằng JavaScript thuần.
- Bài viết nhấn mạnh tầm quan trọng của việc hiểu DOM API của trình duyệt trong phát triển web, dù hiện nay có các công cụ hiện đại như Angular, VueJS, React, Solid và Svelte.
- Tác giả cung cấp một bộ sưu tập tài liệu bao gồm các API trình duyệt cơ bản, ví dụ dễ hiểu, demo thời gian thực, mẹo và thực tiễn tốt nhất, các trường hợp sử dụng thực tế, cùng khả năng tương thích với trình duyệt hiện đại và Internet Explorer.
- Các tài liệu này được chia thành ba cấp độ: cơ bản, trung cấp và nâng cao.
- Ở cấp độ cơ bản có các tác vụ như thay đổi favicon động theo tùy chọn bảng màu của người dùng, tính thời gian đọc của trang web và cập nhật động biến gốc CSS.
- Ở cấp độ trung cấp có các tác vụ như bỏ thụt lề trong vùng văn bản bằng tổ hợp phím Shift+Tab, vào chế độ toàn màn hình và xây dựng input số tăng giảm.
- Ở cấp độ nâng cao có các tác vụ như tạo con trỏ tùy chỉnh, khử độc chuỗi HTML và tạo thanh cuộn tùy chỉnh.
- Tác giả cũng cung cấp các mẹo như tránh bố cục bị xê dịch khi mở modal và lấy hình chữ nhật bao quanh của text node.
- Bài viết kết thúc bằng lời mời đăng ký nhận bản tin của tác giả về nội dung kỹ thuật frontend.
1 bình luận
Ý kiến trên Hacker News
Danh sách ví dụ rất xuất sắc, chỉ cần lướt qua vài cái cũng thấy sự chỉn chu và chi tiết đáng kinh ngạc
Khi chuyển sang các cách triển khai nhỏ hơn, tối giản hơn từ những nền tảng như React, tôi thường bị khựng lại ở chỗ phải xử lý các pattern phức tạp bằng JS chuẩn thế nào, nhưng rồi nhìn vào code mới thấy nhiều lúc lại là kiểu “ơ, cái này còn dễ hơn nhiều so với việc nhét cả đống thuộc tính vào một thư viện khổng lồ”
Ngay cả các framework JS tối giản, khi các yêu cầu tính năng tưởng như vô hại cứ chồng chất lên, cuối cùng cũng rất dễ biến thành quái vật của hook, event và các miếng vá cho side effect
Giờ tôi cũng không dùng jQuery nữa; những thứ như ES module thì tôi dùng để sắp xếp code, nhưng không nhất thiết phải chạy lệnh npm. Đây không phải thứ cần kéo vào như vendor, mà là tiêu chuẩn toàn cục của trình duyệt
Dạo này tôi đọc MDN như kinh thánh. Cứ tin và đi theo là gần như nó dẫn mình tới tận nơi, còn framework thì từ một điểm nào đó lại bắt đầu cản chân. 5 năm trước chưa được như bây giờ, nhưng các browser API đã nhanh chóng hội tụ thành những nền tảng cơ bản mạnh mẽ và nhất quán như module, flexbox, grid
Ví dụ, phần lớn các ví dụ trong bài gốc là loại code mà ngay cả khi dùng React bạn vẫn phải tự viết
Tôi đang làm một side project chưa có tên, kiểu như “vim cho web designer”. Nó tạo website hoặc component trong trình duyệt như Webflow, nhưng mọi thứ được vận hành hoàn toàn bằng ngôn ngữ lệnh
Ban đầu tôi quyết tâm làm mà không dùng framework. Tôi làm việc này từ 2009, dùng JS từ rất lâu trước khi đụng tới framework, nên tôi nghĩ chỉ cần DOM API gốc là đủ
Nhưng việc chuyển dữ liệu ra vào DOM quá tẻ nhạt và dễ lỗi, nên vì sức khỏe tinh thần tôi cuối cùng cũng bắt đầu tự dùng một mini-framework. Lúc đó tôi mới nhớ ra vì sao ban đầu người ta lại dùng framework. Rốt cuộc kiểu gì bạn cũng sẽ dùng framework dưới một dạng nào đó; khác biệt chỉ là đó là thứ tùy biến do bạn tự làm hay chuẩn ngành do cộng đồng tạo ra
Với những site ít tương tác thì DOM gốc vẫn ổn, và phần lớn website dùng React có lẽ thật ra không cần đến nó. Nhưng nếu sản phẩm có dù chỉ một chút sắc thái hay độ phức tạp, tôi sẽ dùng framework để tránh phiền toái. Cuối cùng tôi chuyển sang Svelte và hài lòng hơn hẳn
Với website cần tương tác, thao tác DOM có thể là lựa chọn tốt hơn vì nó dùng kỹ thuật nền tảng và phổ quát hơn, quy trình build nhẹ hoặc không có, chạy nhanh hơn và minh bạch hơn
Tất nhiên có rất nhiều vùng xám, nhưng trường hợp này thuộc chính xác vào nhóm mà framework mang lại lợi ích
Chỉ dùng
value.startsWith('javascript:')là sẽ tạo ra lỗ hổng. Có thể có khoảng trắng tùy ý ở đầu URL, nên ít nhất phải làvalue.trim().startsWith('javascript:')Dù vậy, tôi vẫn nghĩ danh sách cho phép tốt hơn danh sách chặn. Chỉ nên cho phép
http:,https:và nếu cần thì thêmmailto:,ftp:,sftp:; URL tương đối bắt đầu bằng/có lẽ cũng có thể cho phépNhưng vì phải xử lý chính xác mọi thuộc tính thực tế có thể là URL, nên cuối cùng có lẽ tốt hơn là chỉ cho phép một vài thẻ và thuộc tính của chúng
['http:', 'https:', 'mailto:', 'tel:'].includes(new URL(value, location.origin).protocol)[1] https://caniuse.com/url
Bài này không nên tạo cảm giác rằng làm sạch HTML là chuyện dễ dàng như vậy. Dù ở cuối có nhắc tới https://github.com/cure53/DOMPurify, tôi nghĩ đúng ra nên nhấn mạnh hơn nhiều rằng đừng tự viết thứ này và chỉ nên dùng DOMPurify
Tôi đã mở issue về việc này: https://github.com/phuocng/html-dom/issues/281
Có vẻ là một danh sách hữu ích đáng để biết; tôi chưa xem hết nhưng đến giờ trông vẫn ổn
Tôi bấm vào ví dụ đầu tiên thì thấy đang gọi
window.matchMedia('(prefers-color-scheme: dark)')hai lần một cách không cần thiếtNếu định dùng
setFaviconlàm callback cho event listener thì chỉ cần dùngevent.matchestừ tham sốeventđược truyền vào callback là đượcCá nhân tôi thích xử lý ở phía HTML hơn. Vì như vậy vẫn hỗ trợ được cả người dùng đã tắt JS
https://phuoc.ng/collection/html-dom/change-the-favicon-dyna...
theme-color, và với nhà phát triển PWA chú ý đến chi tiết thì đây là một tính năng rất hay dù chưa được dùng nhiềuKỹ thuật “tự động mở rộng
textarea” đang dần lỗi thời vì thuộc tính CSS mới form-sizinghttps://chriscoyier.net/2023/09/29/css-solves-auto-expanding...
Ngay cả khi không dùng thuộc tính CSS mới này, cách điều chỉnh
heightcủa phần tử cũng không lý tưởng và có thể bị giậtCách tiếp cận tốt hơn là dùng một phần tử gương ẩn
https://css-tricks.com/the-cleanest-trick-for-autogrowing-te...
Khá nhiều mục ở đây đang dùng các API cũ và vụng về dù đã có native API tốt hơn
Ví dụ, “thay thế phần tử” được viết là
ele.parentNode.replaceChild(newEle, ele);, nhưng nếu không nhắm tới Chrome dưới 54, Firefox dưới 49, hay Safari dưới 10, thì cứ dùngele.replaceWith(newEle)là đượcreplaceWith cũng có thể thay một node bằng nhiều node hoặc văn bản
Tương tự, ở mục “duyệt NodeList” họ bảo trải mảng rồi dùng
forEach, nhưng chỉ cầnfor (let ele of nodelist) ...là đượcHay. Đã bookmark. Một tài liệu hay khác cùng tinh thần là https://youmightnotneedjquery.com/
Tôi không làm web thường xuyên, nhưng mỗi lần làm là lại hoàn toàn mất hứng vì chứng nghiện framework bên đó. Việc một dự án React mới bắt đầu với hàng trăm dependency đã vượt khỏi tầm kiểm soát, và sức nặng của sự phức tạp đó thật đáng kinh ngạc
Trong khi đó, công nghệ trình duyệt đa nền tảng có sẵn mạnh hơn bao giờ hết, và lượng code để làm các việc phổ biến cũng không nhiều đến thế
Các lập trình viên frontend vẫn ổn chứ?
Ví dụ, quản lý trạng thái ứng dụng và routing là những phần lớn mà nếu chỉ dùng DOM API thuần thì bạn phải tự làm
Tùy độ phức tạp của ứng dụng mà có thể không thành vấn đề gì, nhưng một khi vượt khỏi mức app cơ bản thì giá trị của các tính năng bổ sung này tăng rất nhanh. Chỉ là nếu phải dùng NPM để lấy thứ mình cần thì sẽ đau đầu
Là một lập trình viên frontend yêu thích nền tảng gốc và các tính năng của nó, tôi rất vui khi thấy những thứ hay ho xuất hiện như nested CSS, container query, và trải nghiệm JS nhìn chung tốt hơn kể từ ES6
Đồng thời tôi cũng ngạc nhiên vì quá nhiều người dùng component ngay cả cho những thứ vụn vặt như button hay chữ in đậm
Tôi thích framework bản thân nó, nhưng việc marketing của nhiều framework và thư viện đang dựa vào niềm tin rằng CSS và thao tác DOM thuần khó một cách điên rồ, còn việc kéo đại một package từ NPM về không chỉ nhanh và dễ mà còn là cách làm chuyên nghiệp
Chỉ nhìn vào những thứ như Kubernetes, Helm, Terraform, CircleCI thôi cũng đã thấy lượng thuật ngữ chồng tầng lên nhau là vô lý
Tôi thật sự bất ngờ khi biết nhiều hàm DOM trả về live HTMLCollection tự động cập nhật
Tôi tò mò không biết trước thời kỳ bùng nổ framework, hoặc quanh thời điểm xu hướng phát triển không dùng framework bắt đầu lấy lại chút phổ biến, tính năng này đã từng được dùng tích cực đến mức nào trong code production thực tế
Cái cũ lại thành cái mới. Vai trò frontend đầu tiên của tôi là làm ứng dụng web vào năm 1999
Tôi đã làm mọi thứ bằng JS “Vanilla”, kể cả các tính năng hay ho như kéo thả tree view, click để chỉnh sửa, gần như là ứng dụng một trang
Phần khó nhất là dung hòa sự khác biệt giữa Netscape và Internet Explorer
Sao giờ lại có cảm giác như chúng ta không còn biết làm mấy chuyện đó nữa ;]
Tính năng JavaScript thuần tôi thích nhất dạo này là Element.insertAdjacentHTML, thứ đã có từ thời Chrome 1.0 và IE
Đặc biệt khi dùng cùng chuỗi nhiều dòng với backtick thì mức độ hữu ích phải nói là cực kỳ lớn. Thật khó tin là nó đã tồn tại từ lâu như vậy mà tôi chỉ mới biết đến khoảng một năm trước
insertAdjacentHTML(position, text)sẽ phân tích chuỗi văn bản được chỉ định thành HTML hoặc XML rồi chèn các node kết quả vào vị trí được chỉ định trong cây DOMNếu chỉ dùng DOM thuần theo cách cũ, bạn phải tạo phần tử
li, tạo phần tửa, gắn làm con, đặt thuộc tínhhref, đưa giá trị text vào rồi chèn vàoul. Hoặc phải gom thành một chuỗi lớn rồi đưa vàoinnerHTML, và việc sửa danh sách hiện có còn đau đớn và dài dòng hơn nữa