Now.js Framework Documentation
EventManager
EventManager
ภาพรวม
EventManager คือระบบ event bus กลางใน Now.js Framework สำหรับ component communication
ใช้เมื่อ:
- ต้องการ component-to-component communication
- ต้องการ decouple components
- ต้องการ global event handling
- ต้องการ pub/sub pattern
ทำไมต้องใช้:
- ✅ Global event bus
- ✅ Once listeners
- ✅ Namespaced events
- ✅ Automatic cleanup
- ✅ Event debugging
การใช้งานพื้นฐาน
Emit Event
EventManager.emit('user:login', { user: userData });Listen to Event
EventManager.on('user:login', (data) => {
console.log('User logged in:', data.user);
});Remove Listener
const unsubscribe = EventManager.on('event', handler);
unsubscribe(); // Remove listenerAPI อ้างอิง
EventManager.on(event, handler)
Subscribe to event
| Parameter | Type | Description |
|---|---|---|
event |
string | Event name |
handler |
function | Event handler |
Returns: Function - Unsubscribe function
const unsubscribe = EventManager.on('data:loaded', (data) => {
console.log('Data:', data);
});
// Later...
unsubscribe();EventManager.once(event, handler)
Subscribe once (auto-remove after first call)
EventManager.once('init:complete', () => {
console.log('Initialized!');
});EventManager.emit(event, data?)
Emit event
| Parameter | Type | Description |
|---|---|---|
event |
string | Event name |
data |
any | Event data |
EventManager.emit('cart:update', { items: cart.items });EventManager.off(event, handler?)
Remove listener(s)
| Parameter | Type | Description |
|---|---|---|
event |
string | Event name |
handler |
function | Specific handler (optional) |
// Remove specific handler
EventManager.off('event', myHandler);
// Remove all handlers for event
EventManager.off('event');EventManager.clear()
Remove all listeners
EventManager.clear();Event Naming Convention
ใช้ namespaced events:
// Format: [component]:[action]
'user:login'
'user:logout'
'cart:add'
'cart:remove'
'modal:open'
'modal:close'
'form:submit'
'form:error'ตัวอย่างการใช้งานจริง
Component Communication
// ComponentA.js - Sender
function addToCart(product) {
cart.push(product);
EventManager.emit('cart:add', { product, cart });
}
// ComponentB.js - Receiver
EventManager.on('cart:add', (data) => {
updateCartBadge(data.cart.length);
});
// ComponentC.js - Receiver
EventManager.on('cart:add', (data) => {
showNotification(`Added ${data.product.name}`);
});App State Changes
// Auth events
EventManager.on('auth:login', (data) => {
showUserMenu(data.user);
loadUserPreferences();
});
EventManager.on('auth:logout', () => {
clearUserMenu();
resetApp();
});
// Route events
EventManager.on('route:changed', (data) => {
trackPageView(data.path);
updateActiveNav(data.path);
});Modal Communication
// Open modal and wait for result
function openConfirmModal(message) {
return new Promise((resolve) => {
EventManager.once('confirm:result', (result) => {
resolve(result.confirmed);
});
EventManager.emit('modal:open', {
type: 'confirm',
message
});
});
}
// Usage
const confirmed = await openConfirmModal('Delete this item?');
if (confirmed) {
deleteItem();
}Form Validation
// Global validation listener
EventManager.on('form:validate', (data) => {
console.log('Form validated:', data.valid ? 'PASS' : 'FAIL');
});
// Form emits validation events
function validateForm(form) {
const valid = checkFields(form);
EventManager.emit('form:validate', { form: form.id, valid });
return valid;
}Clean Up on Unmount
class MyComponent {
constructor() {
this.unsubscribers = [];
}
mount() {
// Subscribe and save unsubscribe functions
this.unsubscribers.push(
EventManager.on('event1', this.handler1.bind(this)),
EventManager.on('event2', this.handler2.bind(this))
);
}
unmount() {
// Clean up all subscriptions
this.unsubscribers.forEach(unsub => unsub());
this.unsubscribers = [];
}
}Framework Events
| Event | เมื่อเกิด |
|---|---|
app:ready |
App initialized |
route:changed |
Route changed |
auth:login |
User logged in |
auth:logout |
User logged out |
state:changed |
Global state changed |
modal:open |
Modal opened |
modal:close |
Modal closed |
notification:show |
Notification shown |
ข้อควรระวัง
⚠️ 1. Unsubscribe to Prevent Memory Leaks
// ❌ Never unsubscribe
EventManager.on('event', handler);
// ✅ Save and call unsubscribe
const unsub = EventManager.on('event', handler);
// When done...
unsub();⚠️ 2. Avoid Circular Events
// ❌ Circular - causes infinite loop
EventManager.on('a', () => EventManager.emit('b'));
EventManager.on('b', () => EventManager.emit('a'));
// ✅ Use flags or debounce
let processing = false;
EventManager.on('a', () => {
if (processing) return;
processing = true;
EventManager.emit('b');
processing = false;
});เอกสารที่เกี่ยวข้อง
- ComponentManager - Components
- StateManager - State