در حال بارگذاری...

واگذاری رویداد

پشت باجه یک نوار بلیت است. اسمش #strip است. دو دکمه از قبل رویش نشسته‌اند: #red با متن red، و #blue با متن blue. زیر نوار، بند #note هنوز blank می‌گوید.
لازم نیست روی هر دکمه جدا گوش بدهی. یک بار addEventListener را روی خود نوار می‌گذاری. کلیک هر دکمه‌ای که داخل نوار باشد بالا می‌آید و به همان تابع می‌رسد. event.target همان دکمه است. event.currentTarget خود نوار است، یعنی جایی که شنونده نشسته.
دکمهٔ #gold اول توی صفحه نیست. بعد از ثبت شنونده ساخته می‌شود، به نوار می‌چسبد، و روش کلیک می‌خورد. همان تابع باز هم اجرا می‌شود. بند می‌شود gold. اسکریپت اول red را می‌زند، بعد blue، بعد gold. addEventListener فقط یک بار صدا زده شده، پس hands برابر ۱ است. خط زیر نوار این است: red / blue / gold / 1. این دکمه‌ها type="button" هستند. اینجا preventDefault و stopPropagation نداریم. آن‌ها مال صفحهٔ پلاک بودند، و آنجا بچهٔ تازه هم ساخته نشد.

یک شنونده برای همهٔ بلیت‌ها

صفحهٔ پلاک پارامتر event را داشت و type و target و currentTarget را روی یک لینک می‌خواند. خطش click / seal / plaque / true / quiet بود. چوب‌لباسی wool و silk را بدون پارامتر نگه می‌داشت. خطش wool silk / 2 / peg بود. اینجا پارامتر event می‌ماند، ولی کار target فرق دارد: بگوید کدام بچه کلیک خورده، حتی اگر آن بچه هنوز ساخته نشده بود.
getElementById فقط نوار، دکمهٔ قرمز، دکمهٔ آبی، و بند را می‌دهد. gold از createElement به دنیا می‌آید. اگر روی red یک شنونده بگذاری و روی blue یکی دیگر، gold را نمی‌شنوی مگر بعد از appendChild دوباره بچسبانی. یک شنونده روی نوار به آن چسباندن دوم نیاز ندارد. currentTarget را داخل تابع بخوان. تابع که برگردد، این ویژگی null است.

نوار چه را یادداشت می‌کند

بند از blank شروع می‌شود. نوشتهٔ دکمه‌ها همان red و blue می‌ماند، و gold بعداً می‌آید. ردیف‌ها را به ترتیب بخوان. هر قطعه از نوارِ دو دکمه‌ای شروع می‌شود، جز ردیف صفحه که مال نمایش پایین است. آن نمایش addEventListener را یک بار صدا می‌زند.

📊 نوار چه را یادداشت می‌کند

لحظه چه را می‌خوانی متن بند لغزش رایج
شنونده روی نوار، کلیک روی red event.target.id red خواندن currentTarget که strip است
همان کلیک، خواندن currentTarget event.currentTarget.id strip خواندن شناسهٔ بلیت
همان شنونده، کلیک روی blue event.target.id blue گذاشتن شنوندهٔ جدا روی blue
ساخت gold بعد از شنونده، بعد کلیک event.target.id gold خیال اینکه دکمهٔ تازه ساکت است
کلیک روی خود نوار، با نگهبان بند skip نوشتن شناسهٔ strip
اسکریپت صفحه خط red / blue / gold / 1 خط پلاک، یا تمام شدن با ۳

کلیک روی دکمه یک رویداد است. target برای همهٔ شنونده‌های سر راه همان دکمه می‌ماند. اینجا فقط یک شنونده داریم و روی نوار است، پس تا وقتی تابع در حال اجراست currentTarget همان نوار است. کلیک به نوار می‌رسد چون کسی stopPropagation صدا نزده. صفحهٔ پلاک آن مسیر را می‌برید. اینجا نه.
preventDefault برای کار پیش‌فرض مرورگر است، مثل رفتن یک لینک. این‌ها دکمه هستند، نه لینک. نیاوردن preventDefault یعنی همین صفحه کامل است، نه اینکه خطی جا افتاده باشد.
اگر event.target و event.currentTarget یک گره باشند، کلیک روی خود نوار نشسته، نه روی دکمه. تابع می‌نویسد skip و کاغذ را بلیت حساب نمی‌کند. seen.join(" / ") فقط شناسه‌هایی را به هم می‌چسباند که قبلاً داخل seen رفته‌اند. hands بعد از آن می‌آید. پس واژهٔ آخر تعداد دفعه‌های addEventListener است، نه تعداد کلیک‌ها.

بلیتی که زیر کلیک است

شنونده روی نوار است. تابع پارامتر event دارد و event.target.id را در بند می‌نویسد. بعد صفحه روی red کلیک می‌کند. روی خود red شنونده نمی‌گذارد.

خواندن بلیت

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
note.textContent = event.target.id;
}
strip.addEventListener("click", take);
document.getElementById("red").click();
console.log(note.textContent);

خروجی red است. عنصر شنونده نوار است. target پدر را نمی‌گوید. دکمه‌ای را می‌گوید که زیر کلیک بوده.

صاحب شنونده

باز نوار تازه، همان شنونده، همان کلیک روی red. بند هر دو شناسه را می‌نویسد: اول target، بعد currentTarget.

خواندن هر دو شناسه

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
note.textContent = event.target.id + " " + event.currentTarget.id;
}
strip.addEventListener("click", take);
document.getElementById("red").click();
console.log(note.textContent);

خروجی red strip است. واژهٔ اول بلیت است. واژهٔ دوم عنصری است که این شنونده روی آن نشسته. اگر شنونده را روی خود red بگذاری و روی red کلیک کنی، خروجی red red می‌شود. این خواندن از نوار است، برای همین دو شناسه فرق دارند.

بلیتی که از اول کنارش بوده

دوباره نوار تازه. هنوز یک شنونده، فقط روی نوار. این بار کلیک روی blue است. blue از اول توی نشانه‌گذاری بوده. شنوندهٔ مخصوص خودش را ندارد.

شنیدن بلیت کناری

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
note.textContent = event.target.id;
}
strip.addEventListener("click", take);
document.getElementById("blue").click();
console.log(note.textContent);

خروجی blue است. یک addEventListener هر دو دکمه‌ای را که از قبل داخل نوار بودند پوشش داد. blue جای red را نگرفت. red هم به فراخوانی دوم نیاز نداشت.

بلیتی که دیرتر چاپ می‌شود

اول شنونده ذخیره می‌شود. بعد صفحه یک دکمه می‌سازد، شناسه‌اش را gold می‌گذارد، type را button می‌کند، متن را gold می‌نویسد، و آن را به نوار می‌چسباند. تازه بعدش روی gold کلیک می‌کند.

شنیدن بلیت دیررس

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
note.textContent = event.target.id;
}
strip.addEventListener("click", take);
let gold = document.createElement("button");
gold.id = "gold";
gold.type = "button";
gold.textContent = "gold";
strip.appendChild(gold);
gold.click();
console.log(note.textContent);

خروجی gold است. وقتی addEventListener اجرا شد، gold هنوز نبود. کلیک از gold بالا می‌آید تا نوار، و target همان gold است. روی خود gold شنونده نمی‌گذاری.

کلیک روی کاغذ

خود نوار هم یک گرهٔ قابل کلیک است. اگر target کلیک خود نوار باشد، شناسهٔ بلیتی برای نگه داشتن نیست. تابع target را با currentTarget مقایسه می‌کند. اگر یکی باشند، بند می‌شود skip.

رد کردن کلیک روی نوار

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
if (event.target === event.currentTarget) {
note.textContent = "skip";
return;
}
note.textContent = event.target.id;
}
strip.addEventListener("click", take);
strip.click();
console.log(note.textContent);

خروجی skip است. هم target و هم currentTarget خود نوارند، پس نگهبان کاغذ را رد می‌کند. کلیک روی red هنوز red می‌نویسد، چون آن دو مرجع فرق دارند. نگهبان را بردار و strip.click() شناسهٔ strip را داخل بند می‌نویسد.

خط زیر نوار

اسکریپت ته body است، بعد از اینکه نوار و بندها ساخته شده‌اند. یک شنونده ذخیره می‌شود و hands می‌شود ۱. اول red کلیک می‌خورد، بعد blue. شناسهٔ هر بلیت داخل seen می‌رود. gold ساخته می‌شود، می‌چسبد، و کلیک می‌خورد، پس gold هم می‌رود داخل seen. خط بعد از همین کلیک سوم نوشته می‌شود. صفحه روی خود نوار کلیک نمی‌کند، برای همین skip داخل خط نیست.

نمایش صفحه — نوار بلیت

html
<!DOCTYPE html>
<html>
<head>
<title>event-delegation — page</title>
</head>
<body>
<div id="strip">
<button id="red" type="button">red</button>
<button id="blue" type="button">blue</button>
</div>
<p id="note">blank</p>
<p id="line">…</p>
<script>
let strip = document.getElementById("strip");
let note = document.getElementById("note");
let seen = [];
let hands = 0;
function take(event) {
if (event.target === event.currentTarget) {
note.textContent = "skip";
return;
}
note.textContent = event.target.id;
seen.push(event.target.id);
}
strip.addEventListener("click", take);
hands = hands + 1;
document.getElementById("red").click();
document.getElementById("blue").click();
let gold = document.createElement("button");
gold.id = "gold";
gold.type = "button";
gold.textContent = "gold";
strip.appendChild(gold);
gold.click();
document.getElementById("line").textContent =
seen.join(" / ") + " / " + hands;
</script>
</body>
</html>

خط می‌شود red / blue / gold / 1. سه شناسه، بلیت‌هایی هستند که به ترتیب کلیک خورده‌اند. واژهٔ آخر hands است. addEventListener یک بار اجرا شده، پس آن واژه ۱ است، نه ۳. بند در پایان gold است، چون آخرین کلیک gold بوده. واژهٔ blank رفته. واژهٔ skip اصلاً نمی‌آید. خط پلاک و خط چوب‌لباسی مال صفحه‌های دیگرند.
دکمه‌ای که فقط متن دارد event.target را روی خود دکمه نگه می‌دارد، پس id می‌شود red یا blue یا gold. یک span داخل دکمه بگذاری، کلیک می‌تواند روی span بنشیند. span شناسه ندارد. این صفحه این کار را نمی‌کند.

پای باجه

  1. یک شنونده روی نوار بگذار و روی red کلیک کن. بند red است. خود red شنونده ندارد.
  2. با همان شنونده روی blue کلیک کن. بند blue است.
  3. gold را بساز، بچسبان، و روش کلیک کن. بند gold است. شنونده از قبل روی نوار بود.
  4. روی خود نوار کلیک کن. با نگهبان، بند skip است. بعد خط صفحه را بخوان: red / blue / gold / 1.

لغزش‌های پای باجه

برچسب‌ها هنوز red و blue و gold می‌گویند. بند واژهٔ بلیت نیست.

  • شنونده روی red و یکی دیگر روی blue، بعد تعجب که gold ساکت مانده
  • خواندن event.currentTarget وقتی بلیت را می‌خواستی
  • خواندن event.target وقتی خود نوار را می‌خواستی
  • فراموش کردن نگهبان، طوری که strip.click() بنویسد strip
  • یک span داخل دکمه، طوری که target همان span شود و شناسه خالی بماند
  • صدا زدن دوبارهٔ addEventListener روی gold، بعد شمردن hands به‌صورت ۲
  • صدا زدن preventDefault یا stopPropagation؛ آن مال صفحهٔ پلاک بود
  • انتظار اینکه آرگومان تابع خود عنصر دکمه باشد
  • خواندن خط به شکل click / seal / plaque / true / quiet، یا wool silk / 2 / peg
  • خواندن واژهٔ آخر به‌صورت ۳، چون سه بلیت کلیک خورده‌اند

این را نگه دار

  • یک addEventListener روی نوار، کلیک هر دکمه‌ای داخلش را می‌شنود
  • با کلیک روی red، مقدار event.target.id برابر red است و event.currentTarget.id برابر strip
  • همان شنونده با کلیک روی blue می‌نویسد blue
  • gold که بعد از شنونده ساخته شده باز هم gold می‌نویسد
  • کلیک روی خود نوار، با نگهبان، می‌نویسد skip
  • خط صفحه می‌شود red / blue / gold / 1

🧠 دانش خود را بیازمایید

آماده شروع

دانش خود را بیازمایید

خود را با این آزمون تعاملی به چالش بکشید و ببینید موضوع را چقدر خوب درک کرده‌اید

❓
8
سوالات
🎯
70%
برای قبولی
♾️
∞
زمان
🔄
∞
تلاش‌ها

📝 دستورالعمل‌ها

  • هر سوال را با دقت بخوانید
  • بهترین پاسخ را برای هر سوال انتخاب کنید
  • می‌توانید آزمون را هر چند بار که می‌خواهید تکرار کنید
  • پیشرفت شما در بالا نمایش داده می‌شود