درس ۱۷: رویدادها و تعامل
یادگیری مدیریت رویدادها و ایجاد تعامل کاربر
رویدادها چیستند؟
رویدادها (Events) اتفاقاتی هستند که در صفحه وب رخ میدهند و JavaScript میتواند به آنها واکنش نشان دهد. این رویدادها میتوانند توسط کاربر (مانند کلیک کردن) یا توسط مرورگر (مانند بارگذاری صفحه) ایجاد شوند.
انواع رویدادهای رایج:
- Mouse Events: click, dblclick, mousedown, mouseup, mouseover
- Keyboard Events: keydown, keyup, keypress
- Form Events: submit, change, input, focus, blur
- Window Events: load, resize, scroll
- Touch Events: touchstart, touchend, touchmove
اضافه کردن Event Listeners
روش addEventListener
بهترین روش برای مدیریت رویدادها:
const button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log('دکمه کلیک شد!');
});
// یا با Arrow Function
button.addEventListener('click', () => {
console.log('دکمه کلیک شد!');
});
روشهای دیگر
// روش inline (توصیه نمیشود)
// <button onclick="myFunction()">کلیک</button>
// روش property
button.onclick = function() {
console.log('کلیک شد');
};
// مشکل: فقط یک listener میتواند داشته باشد
تمرین عملی: رویدادها و تعامل
در ادامه، انواع مختلف رویدادها و نحوه مدیریت آنها را تمرین کنید:
ویرایشگر کد
خط 1، ستون 1
نمایش زنده
Event Object
هنگام وقوع یک رویداد، JavaScript یک شیء Event ایجاد میکند که حاوی اطلاعات مفیدی درباره رویداد است:
ویژگیهای مهم Event Object
button.addEventListener('click', function(event) {
console.log('نوع رویداد:', event.type);
console.log('عنصر هدف:', event.target);
console.log('عنصر فعلی:', event.currentTarget);
console.log('موقعیت موس:', event.clientX, event.clientY);
console.log('زمان رویداد:', event.timeStamp);
});
متدهای مهم Event Object
// جلوگیری از رفتار پیشفرض
event.preventDefault();
// توقف انتشار رویداد
event.stopPropagation();
// توقف کامل رویداد
event.stopImmediatePropagation();
Event Delegation
تکنیک قدرتمندی برای مدیریت رویدادها در عناصر متعدد:
// به جای اضافه کردن listener به هر دکمه
const container = document.getElementById('buttonContainer');
container.addEventListener('click', function(e) {
if (e.target.tagName === 'BUTTON') {
console.log('دکمه کلیک شد:', e.target.textContent);
// انجام عمل بر اساس کلاس یا ID
if (e.target.classList.contains('delete-btn')) {
deleteItem(e.target.dataset.id);
} else if (e.target.classList.contains('edit-btn')) {
editItem(e.target.dataset.id);
}
}
});
مزایای Event Delegation
- کاهش مصرف حافظه
- مدیریت عناصر اضافه شده بعداً
- کد تمیزتر و قابل نگهداری
- عملکرد بهتر
رویدادهای مختلف
رویدادهای موس
element.addEventListener('click', handleClick);
element.addEventListener('dblclick', handleDoubleClick);
element.addEventListener('mousedown', handleMouseDown);
element.addEventListener('mouseup', handleMouseUp);
element.addEventListener('mouseover', handleMouseOver);
element.addEventListener('mouseout', handleMouseOut);
element.addEventListener('mousemove', handleMouseMove);
element.addEventListener('contextmenu', handleRightClick);
رویدادهای کیبورد
document.addEventListener('keydown', function(e) {
console.log('کلید فشرده شد:', e.key);
// بررسی کلیدهای خاص
if (e.key === 'Enter') {
console.log('اینتر فشرده شد');
}
// بررسی کلیدهای ترکیبی
if (e.ctrlKey && e.key === 's') {
e.preventDefault();
console.log('Ctrl+S فشرده شد');
}
});
document.addEventListener('keyup', function(e) {
console.log('کلید رها شد:', e.key);
});
رویدادهای فرم
const form = document.getElementById('myForm');
const input = document.getElementById('myInput');
form.addEventListener('submit', function(e) {
e.preventDefault();
console.log('فرم ارسال شد');
});
input.addEventListener('focus', function() {
console.log('فیلد فوکوس شد');
});
input.addEventListener('blur', function() {
console.log('فیلد فوکوس را از دست داد');
});
input.addEventListener('change', function() {
console.log('مقدار تغییر کرد:', this.value);
});
input.addEventListener('input', function() {
console.log('در حال تایپ:', this.value);
});
رویدادهای Touch (لمسی)
برای دستگاههای لمسی مانند موبایل و تبلت:
element.addEventListener('touchstart', function(e) {
console.log('لمس شروع شد');
const touch = e.touches[0];
console.log('موقعیت لمس:', touch.clientX, touch.clientY);
});
element.addEventListener('touchmove', function(e) {
e.preventDefault(); // جلوگیری از اسکرول
const touch = e.touches[0];
console.log('لمس در حرکت:', touch.clientX, touch.clientY);
});
element.addEventListener('touchend', function(e) {
console.log('لمس پایان یافت');
});
Custom Events
ایجاد و ارسال رویدادهای سفارشی:
// ایجاد رویداد سفارشی
const customEvent = new CustomEvent('myCustomEvent', {
detail: {
message: 'این یک رویداد سفارشی است',
timestamp: Date.now()
}
});
// گوش دادن به رویداد سفارشی
element.addEventListener('myCustomEvent', function(e) {
console.log('رویداد سفارشی دریافت شد:', e.detail);
});
// ارسال رویداد
element.dispatchEvent(customEvent);
// مثال کاربردی
function notifyUserAction(action, data) {
const event = new CustomEvent('userAction', {
detail: { action, data, user: getCurrentUser() }
});
document.dispatchEvent(event);
}
document.addEventListener('userAction', function(e) {
console.log(`کاربر ${e.detail.user} انجام داد: ${e.detail.action}`);
});
بهترین شیوهها
💡 نکات مهم:
- حذف Event Listeners: همیشه listeners غیرضروری را حذف کنید
- Event Delegation: برای عناصر متعدد استفاده کنید
- preventDefault: هنگام نیاز از رفتار پیشفرض جلوگیری کنید
- Throttling/Debouncing: برای رویدادهای پرتکرار استفاده کنید
- Passive Listeners: برای بهبود عملکرد استفاده کنید
مثال Debouncing
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// استفاده برای جستجو
const searchInput = document.getElementById('search');
const debouncedSearch = debounce(function(e) {
console.log('جستجو برای:', e.target.value);
// انجام جستجو
}, 300);
searchInput.addEventListener('input', debouncedSearch);
حذف Event Listeners
// تعریف تابع جداگانه
function handleClick() {
console.log('کلیک شد');
}
// اضافه کردن
element.addEventListener('click', handleClick);
// حذف کردن
element.removeEventListener('click', handleClick);
// برای توابع anonymous از AbortController استفاده کنید
const controller = new AbortController();
element.addEventListener('click', function() {
console.log('کلیک شد');
}, { signal: controller.signal });
// حذف همه listeners
controller.abort();