Javascript Và Giấc Mơ Kiểm Soát Reactive
Hành trình tìm cách kiểm soát UI reactive một cách nhẹ, an toàn và linh hoạt từ DOM thủ công, thử nghiệm nhiều framework, đến tự xây reactive engine dựa trên JavaScript Proxy.

Kit Module
@kitmodule
5 phút đọc
10 tháng 08 năm 2025

Hành trình bắt đầu
Khoảng 5 năm trước, tôi từng chia sẻ về một cách tiếp cận rất “cá nhân” khi xây dựng các component trên web: dựa vào Web Component và các custom element.
Ý tưởng của tôi lúc đó khá đơn giản: định nghĩa một element mới, gắn cho nó chức năng riêng, và tương tác trực tiếp với element đó — không phải render lại toàn bộ DOM.
Nếu bạn từng mở YouTube, bấm vào mục View Source, bạn sẽ thấy cách họ tổ chức những custom element và gắn logic riêng biệt cho từng phần. Đó chính là điều truyền cảm hứng cho tôi lúc bắt đầu.
Tôi xây dựng một “engine” nhỏ, cho phép tương tác với từng element một cách độc lập, giảm thiểu tối đa việc can thiệp lại toàn bộ DOM. Mục tiêu rõ ràng: kiểm soát tối đa, tác động tối thiểu.
Khi chính mình bắt đầu nghi ngờ cách làm
Ban đầu, mọi thứ có vẻ hợp lý. Nhưng khi các dự án bắt đầu lớn hơn, tôi nhận ra một thực tế:
- Can thiệp trực tiếp vào DOM tuy mạnh mẽ nhưng không phải lúc nào cũng tối ưu.
- Khi muốn mở rộng hoặc tái sử dụng, tôi phải lặp lại rất nhiều thao tác thủ công.
Điều này khiến tôi đặt câu hỏi: liệu có cách nào vừa tận dụng được triết lý kiểm soát của mình, vừa hưởng lợi từ những tiện ích của các framework JavaScript hiện tại?
Viết lại với triết lý mới
Tôi bắt đầu thử nghiệm lại từ đầu, kết hợp kiến thức mình có với những gì các thư viện và framework đang làm tốt.
Khi tìm hiểu về các khái niệm như Virtual DOM, tôi nhận ra đó là một cách giải quyết vấn đề, nhưng không phải là thứ tôi thực sự cần. Tôi muốn một cách tiếp cận đơn giản hơn.
Và triết lý mới xuất hiện:
Code ít hơn, làm được nhiều hơn.
Trước đây, quy trình của tôi là:
- Đánh dấu DOM.
- Sử dụng JS để tìm và bắt các phần tử.
- Viết logic tương tác trực tiếp lên chúng.
Cách này giúp tôi kiểm soát 100% hành vi, nhưng lại tốn nhiều công sức khi muốn mở rộng hoặc xây dựng các component nhỏ gọn.
Những giải pháp tôi từng nghiên cứu
Tôi tìm hiểu và so sánh các thư viện có triết lý gần giống với những gì tôi làm:
- Alpine.js – nhẹ, dễ tích hợp, cú pháp gần với HTML.
- Web Component – chuẩn web, không phụ thuộc framework, nhưng cần nhiều boilerplate code.
- HTMX – đơn giản, không cần nhiều JavaScript, nhưng thiên về server-driven UI.
- AngularJS 1.x – reactive sớm, nhưng khá nặng nếu chỉ cần tính năng nhỏ.
- Petite-vue – bản thu gọn của Vue, rất nhẹ nhưng vẫn còn những ràng buộc nhất định.
Những giải pháp này đều có điểm mạnh, nhưng tôi vẫn muốn một thứ nhỏ hơn, gọn hơn, kiểm soát nhiều hơn.
Khám phá Proxy và reactive engine đầu tiên
Một bước ngoặt xảy ra vào năm ngoái, khi tôi phát triển một component bảng dữ liệu cho khách hàng. Trong quá trình tìm cách tối ưu cập nhật dữ liệu, tôi phát hiện ra Proxy trong JavaScript — một công cụ cực kỳ mạnh để tạo reactive data mà không cần virtual DOM phức tạp.
Tôi thử áp dụng Proxy và nhận ra nó chạy rất mượt. Nhưng rồi lại gặp một vấn đề quen thuộc: mỗi lần thêm tính năng mới, tôi phải viết lại từ đầu nhiều phần đã có. Vòng lặp phát triển – sửa – viết lại cứ lặp đi lặp lại.
Từ đó, tôi quyết định xây dựng reactive engine đầu tiên của riêng mình, được thiết kế để phục vụ trực tiếp cho cách tôi tổ chức component.
Vì sao tôi không chọn framework JS phổ biến
Tôi không chọn các framework phổ biến như React, Angular hay Vue (bản đầy đủ) vì:
- Chúng quá nặng nề cho nhu cầu của tôi.
- Khó tận dụng hiệu quả với SSR.
- Buộc tôi viết lại nhiều logic backend (hiện tại tôi dùng Golang).
jQuery vẫn tồn tại đến ngày nay vì nó giải quyết nhanh gọn vấn đề thực tế. Nhưng tôi cần một giải pháp nhẹ hơn, hiện đại hơn, và dễ kiểm soát hơn.
Triết lý phát triển: Micro Component
Tôi hình dung Micro Component giống như Microservice:
- Mỗi component chỉ làm đúng một việc.
- Có thể chạy độc lập, không phụ thuộc vào component khác.
- Dễ dàng hydrate (kích hoạt) ở bất kỳ đâu.
Điều này giúp tôi nhúng các mini-app JavaScript vào ứng dụng di động hoặc website mà không ảnh hưởng đến các phần khác.
Vì SEO đã được tối ưu từ server, tôi chỉ cần tập trung vào nâng cao trải nghiệm người dùng ở client.
Ví dụ: cú pháp micro component
Đây là một ví dụ cho component đếm đơn giản (counter) theo cách tôi triển khai:
Ở đây:
- data-kitmodule-component định danh component.
- data-counter-state khai báo state ban đầu.
- data-counter-model binding dữ liệu hai chiều với input.
- data-counter-event gắn event handler trực tiếp qua attribute.
- data-counter-bind cập nhật DOM khi state thay đổi.
Kết quả là một component nhỏ gọn, không phụ thuộc framework lớn, nhưng vẫn reactive.
Hành trình này cho tôi thấy rằng đôi khi sự đơn giản mới là tối thượng. Reactive không nhất thiết phải đi kèm với virtual DOM nặng nề hay cú pháp phức tạp.
Chỉ cần một engine nhỏ, cú pháp HTML-based dễ đọc, và một chút JavaScript tinh gọn là đủ để tạo nên những trải nghiệm người dùng mượt mà.
Trong phần tiếp theo, tôi sẽ chia sẻ chi tiết kiến trúc của reactive engine này, cách nó parse biểu thức, gắn event, và đồng bộ state với DOM mà không cần eval hay Function constructor — đảm bảo an toàn CSP và tránh XSS.
16
lượt xem
Bài Viết Liên Quan

Chỉ là mình thích cách lập trình web của mình. Có thể tùy chỉnh theo ý thích và không phụ thuộc vào framework.

Cuối cùng, tôi vẫn tự hỏi: “Nếu có một dự án lớn, mình sẽ làm gì?”. Tôi chẳng có gì ngoài những nợ nần và niềm đam mê. Nhưng tôi biết, chỉ cần còn đam mê, tôi vẫn sẽ bước tiếp. "Coding and life" - đó là cách mà kẻ dại khờ này tiếp tục.

Hành trình của tôi không bắt đầu ở một công ty lớn, cũng chẳng gắn liền với những startup gọi vốn hàng triệu đô. Nó bắt đầu từ một chiếc laptop cũ, từ căn phòng nhỏ ở quê nhà Tam Kỳ, nơi tôi vừa làm việc, vừa tự học code – và mang trong mình một khát khao duy nhất: “ Làm chủ công nghệ. Tạo ra giá trị thực bằng chính đôi tay mình.”

Mười năm mơ kết mây thành hoa trắng. Mây vỡ, hoa tan – tàn giấc mơ hoa. Nhưng giấc mơ hoa này, ta xin mơ một lần... Vì đời này, ta chỉ có một giấc mơ. Và một cuộc đời.

Sau hơn 1 năm chật vật với kinh tế. Tôi chỉ có 2 khách hàng đầu tiên từ website và ads. Tôi ngồi nói chuyện vu vơ với vài người bạn, tôi nhận ra rằng? Tại sao mình không sử dụng các data của mình đã thu thập để làm affiliate. Vậy là samdy ra đời, tôi viết một website về tìm kiếm sản phẩm giá tốt trên 3 nền tảng lazada, tiki và shopee.

Có vẽ dạo gần đây có nhiều câu chuyện về quảng cáo Youtube và sự can thiệp của Server Side Render từ sever của youtube đang dần trở nên phổ biến. Bài viết này sẽ chia sẽ những điều tôi biết vê Server Side Rendering...

Thế giới công nghệ phát triển nhanh chóng, và một trong những bước tiến thú vị mà tôi có cơ hội tiếp cận là hệ giao thức phân tán. Cơ hội này mở ra từ những nhu cầu tưởng chừng đơn giản như xây dựng một ứng dụng chat trực tiếp giữa các thiết bị mà không cần máy chủ trung gian. Điều này đưa tôi đến với các giao thức phân tán như WebRTC và các phương pháp truyền dữ liệu ngang hàng (Peer-to-Peer, hay P2P).

Nếu trước đó bạn đã biết câu chuyện về logo của Xiaomi với giá 300.000 đô la, thì hôm nay tôi có một câu chuyện với giá dưới 300.000 đồng.

Khi bản thân tự định hướng cho mình một lối đi. Một con đường và một ánh sáng thì cứ đi theo ánh sáng đó.

Có lẽ trên con đường Affiliate Hay trở thành Một Top Publisher sẽ không ít khó khăn ở từng giai đoạn nhưng Affiliate đã đưa mình vào những thành tựu bản thân muốn đạt được từ những bước chân đầu tiên. Với chỉ 14 nghìn một tháng, ăn cơm nhà và dám mơ ước được những điều lớn lao sau này. Trong ước vọng của trái tim nhỏ bé này chưa bao giờ ngừng mơ ước hoài bão, về điều gì đó có thể hình thành.