JavaScript DOM 事件完全参考手册
📋 事件分类总览
JavaScript DOM事件按照功能可分为以下9大类:
🖱️ 1. 鼠标事件 (Mouse Events)
事件名 |
触发时机 |
常用属性 |
示例代码 |
click |
单击元素 |
clientX , clientY |
element.onclick = () => {} |
dblclick |
双击元素 |
detail |
element.ondblclick = () => {} |
mousedown |
鼠标按下 |
button , buttons |
element.onmousedown = (e) => { console.log(e.button) } |
mouseup |
鼠标释放 |
button , buttons |
element.onmouseup = () => {} |
mouseover |
鼠标移入 |
relatedTarget |
element.onmouseover = () => {} |
mouseout |
鼠标移出 |
relatedTarget |
element.onmouseout = () => {} |
mousemove |
鼠标移动 |
clientX , clientY |
element.onmousemove = (e) => { console.log(e.clientX) } |
mouseenter |
鼠标进入(不冒泡) |
- |
element.onmouseenter = () => {} |
mouseleave |
鼠标离开(不冒泡) |
- |
element.onmouseleave = () => {} |
鼠标事件示例:
const button = document.querySelector('#myButton');
button.addEventListener('mouseenter', () => {
button.style.backgroundColor = '#ff6b6b';
});
button.addEventListener('mouseleave', () => {
button.style.backgroundColor = '#4ecdc4';
});
document.addEventListener('click', (event) => {
console.log(`鼠标位置: X=${event.clientX}, Y=${event.clientY}`);
});
⌨️ 2. 键盘事件 (Keyboard Events)
事件名 |
触发时机 |
常用属性 |
示例代码 |
keydown |
按键按下 |
key , code , ctrlKey |
input.onkeydown = (e) => { console.log(e.key) } |
keyup |
按键释放 |
key , code |
input.onkeyup = () => {} |
keypress |
字符输入(已废弃) |
charCode |
不推荐使用 |
键盘事件示例:
document.addEventListener('keydown', (event) => {
if (event.ctrlKey && event.key === 's') {
event.preventDefault();
console.log('保存快捷键触发');
}
});
const searchInput = document.querySelector('#search');
searchInput.addEventListener('input', (e) => {
console.log(`搜索内容: ${e.target.value}`);
});
📋 3. 表单事件 (Form Events)
事件名 |
触发时机 |
适用元素 |
示例代码 |
submit |
表单提交 |
<form> |
form.onsubmit = (e) => { e.preventDefault() } |
reset |
表单重置 |
<form> |
form.onreset = () => {} |
change |
值改变并失焦 |
<input> , <select> |
select.onchange = () => {} |
input |
实时输入变化 |
<input> , <textarea> |
input.oninput = () => {} |
focus |
获得焦点 |
所有表单元素 |
input.onfocus = () => {} |
blur |
失去焦点 |
所有表单元素 |
input.onblur = () => {} |
invalid |
验证失败 |
表单元素 |
input.oninvalid = () => {} |
表单验证示例:
const emailInput = document.querySelector('#email');
emailInput.addEventListener('input', () => {
const isValid = emailInput.checkValidity();
emailInput.style.borderColor = isValid ? 'green' : 'red';
});
document.querySelector('#myForm').addEventListener('submit', (event) => {
event.preventDefault();
const formData = new FormData(event.target);
console.log(Object.fromEntries(formData));
});
🌐 4. 文档/窗口事件 (Document/Window Events)
事件名 |
触发时机 |
作用域 |
示例代码 |
load |
页面完全加载 |
window |
window.onload = () => {} |
DOMContentLoaded |
DOM加载完成 |
document |
document.addEventListener('DOMContentLoaded', () => {}) |
beforeunload |
页面即将卸载 |
window |
window.onbeforeunload = () => '确认离开?' |
unload |
页面卸载 |
window |
window.onunload = () => {} |
resize |
窗口大小改变 |
window |
window.onresize = () => {} |
scroll |
页面滚动 |
window |
window.onscroll = () => {} |
online/offline |
网络状态变化 |
window |
window.ononline = () => {} |
页面生命周期示例:
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM已加载,可以安全操作DOM');
});
let resizeTimer;
window.addEventListener('resize', () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
console.log(`窗口大小: ${window.innerWidth}x${window.innerHeight}`);
}, 250);
});
let ticking = false;
window.addEventListener('scroll', () => {
if (!ticking) {
requestAnimationFrame(() => {
console.log(`滚动位置: ${window.scrollY}px`);
ticking = false;
});
ticking = true;
}
});
📱 5. 触摸事件 (Touch Events - 移动端)
事件名 |
触发时机 |
移动端特有 |
示例代码 |
touchstart |
触摸开始 |
✅ |
element.ontouchstart = (e) => {} |
touchend |
触摸结束 |
✅ |
element.ontouchend = () => {} |
touchmove |
触摸移动 |
✅ |
element.ontouchmove = (e) => {} |
touchcancel |
触摸中断 |
✅ |
element.ontouchcancel = () => {} |
移动端触摸示例:
let touchStartX = 0;
let touchEndX = 0;
document.addEventListener('touchstart', (e) => {
touchStartX = e.changedTouches[0].screenX;
});
document.addEventListener('touchend', (e) => {
touchEndX = e.changedTouches[0].screenX;
handleSwipe();
});
function handleSwipe() {
if (touchEndX < touchStartX - 50) {
console.log('左滑');
}
if (touchEndX > touchStartX + 50) {
console.log('右滑');
}
}
🎯 6. 拖放事件 (Drag & Drop Events)
事件名 |
触发时机 |
拖放阶段 |
示例代码 |
dragstart |
开始拖动 |
源元素 |
element.ondragstart = (e) => {} |
drag |
拖动中 |
源元素 |
element.ondrag = () => {} |
dragend |
拖动结束 |
源元素 |
element.ondragend = () => {} |
dragenter |
进入目标区域 |
目标元素 |
target.ondragenter = () => {} |
dragover |
在目标区域上方 |
目标元素 |
target.ondragover = (e) => { e.preventDefault() } |
dragleave |
离开目标区域 |
目标元素 |
target.ondragleave = () => {} |
drop |
放置完成 |
目标元素 |
target.ondrop = (e) => {} |
拖放功能示例:
const dropZone = document.querySelector('#drop-zone');
const dragItems = document.querySelectorAll('.draggable');
dragItems.forEach(item => {
item.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', e.target.id);
e.target.classList.add('dragging');
});
item.addEventListener('dragend', (e) => {
e.target.classList.remove('dragging');
});
});
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
dropZone.classList.add('drag-over');
});
dropZone.addEventListener('dragleave', () => {
dropZone.classList.remove('drag-over');
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
const id = e.dataTransfer.getData('text/plain');
const draggedElement = document.getElementById(id);
dropZone.appendChild(draggedElement);
dropZone.classList.remove('drag-over');
});
📋 7. 剪贴板事件 (Clipboard Events)
事件名 |
触发时机 |
现代支持 |
示例代码 |
copy |
复制操作 |
✅ |
element.oncopy = (e) => {} |
cut |
剪切操作 |
✅ |
element.oncut = (e) => {} |
paste |
粘贴操作 |
✅ |
element.onpaste = (e) => {} |
剪贴板操作示例:
const copyButton = document.querySelector('#copy-btn');
copyButton.addEventListener('click', async () => {
const text = document.querySelector('#text-to-copy').value;
try {
await navigator.clipboard.writeText(text);
console.log('已复制到剪贴板');
} catch (err) {
console.error('复制失败:', err);
}
});
document.addEventListener('paste', (e) => {
const pastedData = e.clipboardData.getData('text/plain');
console.log('粘贴内容:', pastedData);
});
🎵 8. 媒体事件 (Media Events)
事件名 |
触发时机 |
适用元素 |
示例代码 |
play |
播放开始 |
<audio> , <video> |
video.onplay = () => {} |
pause |
播放暂停 |
<audio> , <video> |
video.onpause = () => {} |
ended |
播放结束 |
<audio> , <video> |
video.onended = () => {} |
timeupdate |
播放时间更新 |
<audio> , <video> |
video.ontimeupdate = () => {} |
volumechange |
音量变化 |
<audio> , <video> |
video.onvolumechange = () => {} |
loadedmetadata |
元数据加载 |
<audio> , <video> |
video.onloadedmetadata = () => {} |
progress |
加载进度 |
<audio> , <video> |
video.onprogress = () => {} |
error |
加载错误 |
<audio> , <video> |
video.onerror = () => {} |
媒体控制示例:
const video = document.querySelector('#my-video');
const playBtn = document.querySelector('#play-btn');
const progressBar = document.querySelector('#progress-bar');
playBtn.addEventListener('click', () => {
if (video.paused) {
video.play();
playBtn.textContent = '暂停';
} else {
video.pause();
playBtn.textContent = '播放';
}
});
video.addEventListener('timeupdate', () => {
const progress = (video.currentTime / video.duration) * 100;
progressBar.style.width = `${progress}%`;
});
video.addEventListener('loadedmetadata', () => {
console.log(`视频时长: ${video.duration}秒`);
});
🔄 9. 其他重要事件
事件名 |
触发时机 |
应用场景 |
示例代码 |
hashchange |
URL hash变化 |
单页应用 |
window.onhashchange = () => {} |
popstate |
浏览器历史导航 |
路由管理 |
window.onpopstate = () => {} |
storage |
localStorage变化 |
跨标签通信 |
window.onstorage = () => {} |
animationstart |
CSS动画开始 |
动画同步 |
element.onanimationstart = () => {} |
animationend |
CSS动画结束 |
动画清理 |
element.onanimationend = () => {} |
transitionend |
CSS过渡结束 |
状态更新 |
element.ontransitionend = () => {} |
🛠️ 事件处理最佳实践
1. 事件委托模式
document.querySelectorAll('.item').forEach(item => {
item.addEventListener('click', handleClick);
});
document.querySelector('#list-container').addEventListener('click', (e) => {
if (e.target.classList.contains('item')) {
handleClick(e);
}
});
2. 防抖和节流
function debounce(func, delay) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), delay);
};
}
function throttle(func, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
window.addEventListener('resize', debounce(() => {
console.log('窗口大小改变');
}, 250));
window.addEventListener('scroll', throttle(() => {
console.log('页面滚动');
}, 100));
3. 事件移除
function handleClick(event) {
console.log('点击事件');
}
button.addEventListener('click', handleClick);
button.removeEventListener('click', handleClick);
4. 自定义事件
const customEvent = new CustomEvent('myCustomEvent', {
detail: { message: 'Hello World' },
bubbles: true,
cancelable: true
});
element.addEventListener('myCustomEvent', (e) => {
console.log('收到自定义事件:', e.detail.message);
});
element.dispatchEvent(customEvent);
📊 事件兼容性检查
function isEventSupported(eventName, element = document.createElement('div')) {
const eventNameUpper = 'on' + eventName.toLowerCase();
return (eventNameUpper in element) || (element.setAttribute && element.setAttribute(eventNameUpper, 'return;') && typeof element[eventNameUpper] === 'function');
}
console.log('Touch事件支持:', isEventSupported('touchstart'));
console.log('Pointer事件支持:', isEventSupported('pointerdown'));
🎯 常用事件速查表
事件类型 |
使用场景 |
推荐绑定方式 |
click |
按钮点击 |
addEventListener |
input |
实时输入验证 |
addEventListener |
submit |
表单提交 |
onsubmit + preventDefault |
DOMContentLoaded |
页面初始化 |
addEventListener |
resize |
响应式布局 |
节流处理 |
scroll |
无限滚动 |
节流处理 |
keydown |
快捷键 |
addEventListener |
touchstart |
移动端手势 |
addEventListener |
dragover |
文件拖拽上传 |
preventDefault |
paste |
粘贴处理 |
addEventListener |
这份手册涵盖了JavaScript DOM事件的所有重要类型和使用场景,可以作为日常开发的快速参考。
所有评论(0)