Events: Advanced (Event Delegation, Custom Events)
Event delegation, dynamic list, custom events, dispatchEvent, passive listeners — গভীর ইভেন্ট দক্ষতা বাংলায়।
শেষ পর্বে delegation, custom events, listener management আর performance নিয়ে — বড় অ্যাপ-এ ইভেন্ট-কে পরিষ্কার ও দ্রুত রাখার কৌশল।
Event delegation — আবার, গভীর করে
document.getElementById("list").addEventListener("click", (e) => {
const li = e.target.closest("li[data-id]");
if (!li) return;
const id = li.dataset.id;
console.log("Clicked item", id);
});
// পরে list-এ নতুন element যোগ করা হোক — delegation-এ কাজ করবেইe.target.closest(...) দিয়ে কী চাপা পড়েছে শনাক্ত করা হয়। delegation-এর সুবিধা: কম listener, dynamic items-এর কাজ, memory ছোট।
Delegation সঙ্গের সাথে data
<button data-action="delete" data-id="1">মুছুন</button>
<script>
document.body.addEventListener("click", (e) => {
const btn = e.target.closest("[data-action]");
if (!btn) return;
const { action, id } = btn.dataset;
if (action === "delete") {
console.log("delete", id);
}
});
</script>data-action + data-* প্যাটার্ন দিয়ে কেন্দ্রীয় এক listener-এ সব action ঠিক করা যায় — আরও button যোগ করলেও নতুন code কম লাগে।
Custom events — Event(), dispatchEvent()
const el = document.getElementById("widget");
// নতুন ইভেন্ট বানানো + বিস্তারিত
el.addEventListener("app:update", (e) => {
console.log("ডেটা:", e.detail);
});
// পাঠানো
el.dispatchEvent(
new CustomEvent("app:update", {
detail: { count: 42 },
}),
);new CustomEvent(name, { detail }) নিজস্ব ইভেন্ট — component-গুলোকে বার্তা দেওয়ার পরিষ্কার উপায়। detail-এ যেকোনো ডেটা। ইভেন্ট-এর নামে namespace (app: দিয়ে) এড়াতে সংঘর্ষ।
Keyboard events ও shortcut
document.addEventListener("keydown", (e) => {
// shortcut
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "s") {
e.preventDefault();
saveDocument();
}
});Listening-এর memory management
const listeners = [];
function track(handler) {
window.addEventListener("resize", handler);
listeners.push(handler);
}
// cleanup
function cleanup() {
listeners.forEach((h) => window.removeEventListener("resize", h));
listeners.length = 0;
}DOM element মুছে যাওয়ার পরও listener স্মৃতিতে থাকে — SPA-তে কৌশল: যার listener আর দরকার নেই তা খুঁজে বের করে remove করুন।
passive listeners
window.addEventListener(
"scroll",
onScroll,
{ passive: true }, // preventDefault ব্যবহার করব না — দ্রুত
);
// passive: false হলে preventDefault দরকারি — scroll locktouchmove/scroll-এ { passive: true } ব্রাউজারকে জানায় preventDefault হবে না — মসৃণ scroll-এর জন্য।
once + AbortController
const controller = new AbortController();
const { signal } = controller;
window.addEventListener("resize", handleResize, { signal });
document.addEventListener("scroll", handleScroll, { signal });
// একবারে সব বন্ধ
controller.abort(); // remove সবAbortController দিয়ে একাধিক listener-কে এক snapshot-এ remove করা যায় — cleanup-এর স্মার্ট পদ্ধতি।
| কৌশল | উদাহরণ |
|---|---|
| delegation | parent-এ এক listener |
| CustomEvent | component-বার্তা |
| passive | scroll/touch-সহজ |
| AbortController | bulk cleanup |
"Delegation কেন দরকার?" — কম listener, dynamic items, স্মৃতি। "Custom event কখন?" — component-এর মধ্যে বার্তা, detail সহ।
একটি todo list: add/delete-ই delegation দিয়ে, আর প্রতিটি কাজের পরে 'todos:updated' custom event পাঠান — অন্য অংশ শুনে তার পর count আপডেট করবে।