
Signals trong JavaScript: Cơ chế reactivity mới cho UI hiện đại
Trong thế giới phát triển frontend hiện đại, việc quản lý trạng thái và cập nhật giao diện một cách hiệu quả là thách thức lớn. Signals đang nổi lên như một giải pháp mạnh mẽ, cung cấp cơ chế reactivity tinh vi giúp các ứng dụng phản hồi nhanh hơn và code trở nên sạch hơn.
Signals là gì?
Signals là một primitive reactivity cho phép tracking tự động các phụ thuộc và kích hoạt cập nhật khi dữ liệu thay đổi. Khác với cách tiếp cận truyền thống, Signals hoạt động dựa trên nguyên tắc getter/setter đơn giản nhưng mạnh mẽ:
- Getter: Khi bạn đọc giá trị của một signal, hệ thống sẽ tự động tracking nơi giá trị đó được sử dụng
- Setter: Khi bạn thay đổi giá trị, tất cả các vị trí phụ thuộc sẽ được thông báo và cập nhật tự động
- Computed signals: Tạo ra các giá trị dẫn xuất từ các signals khác, chỉ tính toán lại khi phụ thuộc thực sự thay đổi

Tại sao Signals lại quan trọng?
React sử dụng Virtual DOM và reconciliation để cập nhật UI, nhưng cách này có chi phí đáng kể khi ứng dụng phát triển. Signals đưa ra cách tiếp cận khác:
| Khía cạng | Cách tiếp cận truyền thống | Signals |
|---|---|---|
| Tracking phụ thuộc | Cần khai báo rõ ràng (useEffect, watch) | Tự động qua getter access |
| Cập nhật UI | Toàn bộ subtree có thể render lại | Chỉ các thành phần thực sự phụ thuộc |
| Boilerplate code | Nhiều hook và dependencies array | Code trực tiếp, ít boilerplate |
| Hiệu năng | Có thể cần memoization phức tạp | Tối ưu tự động, tính toán lazy |
Signals trong các framework khác nhau
SolidJS — Nhà tiên phong áp dụng Signals
SolidJS sử dụng Signals như nền tảng reactivity cốt lõi. API đơn giản và mạnh mẽ:
import { createSignal } from "solid-js";
// Tạo signal
const [count, setCount] = createSignal(0);
// Đọc giá trị
console.log(count()); // 0
// Cập nhật giá trị
setCount(count() + 1);
// Computed signal
const doubleCount = () => count() * 2;
SolidJS đạt được hiệu năng xuất sắc nhờ cập nhật hữu hạn chỉ những thành phần thực sự thay đổi, không dựa trên Virtual DOM.
Preact — Signals tích hợp từ phiên bản 10
Preact mang Signals vào core với kích thước bundle rất nhỏ (khoảng 1.6KB):
import { signal, computed } from "@preact/signals";
const count = signal(0);
const double = computed(() => count.value * 2);
// Trong component
function Counter() {
return (
<button onClick={() => count.value++}>
Count: {count} x2 = {double}
</button>
);
}
Preact Signals hoạt động tốt cả trong components bên ngoài và bên trong, không phụ thuộc vào hooks.
Angular — Signals tích hợp core framework từ phiên bản 16
Angular cung cấp Signals như một phần của hệ thống reactivity mới, tương thích tốt với Zone.js:
import { signal, computed, effect } from '@angular/core';
const count = signal(0);
const doubleCount = computed(() => count() * 2);
// Effect chạy tự động khi count thay đổi
effect(() => console.log('Count is:', count()));
Angular Signals được thiết kế để làm việc liền mạch với signal detection hiện có, đồng thời chuẩn bị cho tương lai không cần Zone.js.

Vue — Tích hợp Signals qua Composition API
Vue.js đã có hệ thống reactivity mạnh mẽ thông qua ref() và reactive(). Vue 3.3+ bắt đầu khám phá việc tích hợp Signals nguyên bản:
import { ref, computed, watchEffect } from 'vue';
const count = ref(0);
const doubleCount = computed(() => count.value * 2);
watchEffect(() => {
console.log(`Count is: ${count.value}`);
});
Đội ngũ Vue đang nghiên cứu “Vapor Mode” — một chiến lược biên dịch mới lấy cảm hứng từ SolidJS để tối ưu hơn nữa mà không cần Virtual DOM.
TC39 Signals Proposal — Chuẩn hoá trong tương lai
TC39 Signals proposal (đang ở Stage 1) nhằm chuẩn hoá semantics cốt lõi của signals để các framework có thể xây dựng trên nền tảng chung. Điều này sẽ giúp:
- Tăng tính tương tác giữa các framework
- Giảm kích thước bundle khi không cần polyfill cho từng framework
- Cung cấp API cấp thấp để các thư viện tiện ích xây dựng trên đó
Mặc dù còn ở giai đoạn sớm, proposal đã nhận được sự hỗ trợ từ các nhà phát triển chính của Angular, Solid, Preact, Qwik, Svelte và nhiều framework khác.
Lợi ích thực tế khi sử dụng Signals
Dựa trên kinh nghiệm từ các ứng dụng thực tế, Signals mang lại những lợi ích cụ thể:
- Hiệu năng tốt hơn: Giảm lượng công việc không cần thiết trong quá trình render
- Trải nghiệm phát triển tốt hơn: Code trực tiếp, ít boilerplate, dễ gỡ lỗi
- Tính dự đoán cao: Luôn biết chính xác khi nào và tại sao một phần UI sẽ cập nhật
- Dễ học cho người mới: Khái niệm getter/setter đơn giản hơn Virtual DOM reconciliation
- Tích hợp tốt: Có thể sử dụng Signals cùng với các cách quản lý state hiện có
Kết luận
Signals đang mở ra một kỷ nguyên mới cho reactivity trong JavaScript. Vừa đơn giản để hiểu, vừa mạnh mẽ trong ứng dụng thực tế, Signals không chỉ là một xu hướng tạm thời mà là bước tiến quan trọng trong cách chúng ta xây dựng ứng dụng web.
Với sự hỗ trợ ngày càng tăng từ các framework chính và tiến bộ của TC39 proposal, Signals sẽ trở thành một phần không thể thiếu trong công cụ của mọi frontend developer. Hãy khám phá Signals ngay hôm nay để chuẩn bị cho tương lai của phát triển web hiện đại.

