与浏览器窗口相关的事件。
// 页面加载完成
window.addEventListener("load", function() {
console.log("页面加载完成");
});
// 图片加载完成
const img = document.querySelector("img");
img.addEventListener("load", function() {
console.log("图片加载完成");
});
// 脚本加载完成
const script = document.createElement("script");
script.src = "app.js";
script.addEventListener("load", function() {
console.log("脚本加载完成");
});
document.head.appendChild(script);
// DOM解析完成(不等图片等资源)
document.addEventListener("DOMContentLoaded", function() {
console.log("DOM已就绪");
// 可以安全操作DOM
});
// 比load更早触发
// DOMContentLoaded → load
// 页面卸载时
window.addEventListener("unload", function() {
// 发送统计数据
navigator.sendBeacon("/analytics", data);
});
// beforeunload - 可以提示用户
window.addEventListener("beforeunload", function(e) {
e.preventDefault();
e.returnValue = "确定离开吗?";
});
// 窗口大小改变
window.addEventListener("resize", function() {
console.log("窗口大小:", window.innerWidth, window.innerHeight);
});
// 使用防抖优化
let resizeTimer;
window.addEventListener("resize", function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
console.log("调整完成");
}, 200);
});
// 页面滚动
window.addEventListener("scroll", function() {
console.log("滚动位置:", window.scrollY);
});
// 元素滚动
const container = document.querySelector(".container");
container.addEventListener("scroll", function() {
console.log("元素滚动:", this.scrollTop);
});
与鼠标操作相关的事件。
const button = document.querySelector("button");
// click - 点击
button.addEventListener("click", function(e) {
console.log("点击");
});
// dblclick - 双击
button.addEventListener("dblclick", function(e) {
console.log("双击");
});
// 触发顺序:mousedown → mouseup → click
// mousedown - 鼠标按下
element.addEventListener("mousedown", function(e) {
console.log("鼠标按下");
console.log("按钮:", e.button); // 0左 1中 2右
});
// mouseup - 鼠标抬起
element.addEventListener("mouseup", function(e) {
console.log("鼠标抬起");
});
// mousemove - 鼠标移动
element.addEventListener("mousemove", function(e) {
console.log("位置:", e.clientX, e.clientY);
});
// mouseenter - 鼠标进入(不冒泡)
element.addEventListener("mouseenter", function(e) {
console.log("鼠标进入");
});
// mouseleave - 鼠标离开(不冒泡)
element.addEventListener("mouseleave", function(e) {
console.log("鼠标离开");
});
// mouseover - 鼠标悬停(冒泡)
element.addEventListener("mouseover", function(e) {
console.log("鼠标悬停");
});
// mouseout - 鼠标移出(冒泡)
element.addEventListener("mouseout", function(e) {
console.log("鼠标移出");
});
element.addEventListener("click", function(e) {
// 鼠标位置
console.log("相对视口:", e.clientX, e.clientY);
console.log("相对页面:", e.pageX, e.pageY);
console.log("相对元素:", e.offsetX, e.offsetY);
console.log("相对屏幕:", e.screenX, e.screenY);
// 修饰键
console.log("Ctrl:", e.ctrlKey);
console.log("Shift:", e.shiftKey);
console.log("Alt:", e.altKey);
console.log("Meta:", e.metaKey);
// 鼠标按钮
console.log("按钮:", e.button);
console.log("按钮:", e.buttons); // 组合值
});
| e.button值 | 含义 |
|---|---|
| 0 | 左键 |
| 1 | 中键(滚轮) |
| 2 | 右键 |
| 3 | 后退按钮 |
| 4 | 前进按钮 |
与键盘操作相关的事件。
// keydown - 按键按下
document.addEventListener("keydown", function(e) {
console.log("按下:", e.key);
});
// keyup - 按键抬起
document.addEventListener("keyup", function(e) {
console.log("抬起:", e.key);
});
// keypress - 已废弃,不推荐使用
document.addEventListener("keydown", function(e) {
// 按键值
console.log("key:", e.key); // "a", "Enter", "ArrowUp"
console.log("code:", e.code); // "KeyA", "Enter", "ArrowUp"
console.log("keyCode:", e.keyCode); // 已废弃
// 修饰键
console.log("Ctrl:", e.ctrlKey);
console.log("Shift:", e.shiftKey);
console.log("Alt:", e.altKey);
console.log("Meta:", e.metaKey);
// 是否重复按下
console.log("重复:", e.repeat);
});
document.addEventListener("keydown", function(e) {
// 特殊键
switch(e.key) {
case "Enter":
console.log("回车");
break;
case "Escape":
console.log("ESC");
break;
case "Tab":
console.log("Tab");
break;
case "Backspace":
console.log("退格");
break;
case "Delete":
console.log("删除");
break;
case "ArrowUp":
case "ArrowDown":
case "ArrowLeft":
case "ArrowRight":
console.log("方向键:", e.key);
break;
case " ":
console.log("空格");
break;
}
});
document.addEventListener("keydown", function(e) {
// Ctrl + S 保存
if (e.ctrlKey && e.key === "s") {
e.preventDefault();
save();
}
// Ctrl + Shift + S 另存为
if (e.ctrlKey && e.shiftKey && e.key === "S") {
e.preventDefault();
saveAs();
}
// Ctrl + Z 撤销
if (e.ctrlKey && e.key === "z") {
e.preventDefault();
undo();
}
});
与元素获取/失去焦点相关的事件。
const input = document.querySelector("input");
// focus - 获取焦点(不冒泡)
input.addEventListener("focus", function(e) {
console.log("获取焦点");
this.style.borderColor = "blue";
});
// blur - 失去焦点(不冒泡)
input.addEventListener("blur", function(e) {
console.log("失去焦点");
this.style.borderColor = "";
});
// focusin - 获取焦点(冒泡)
input.addEventListener("focusin", function(e) {
console.log("focusin");
});
// focusout - 失去焦点(冒泡)
input.addEventListener("focusout", function(e) {
console.log("focusout");
});
<form id="myForm">
<input type="text" name="username">
<input type="password" name="password">
</form>
<script>
const form = document.getElementById("myForm");
// 使用冒泡版本在父元素监听
form.addEventListener("focusin", function(e) {
console.log("聚焦:", e.target.name);
});
form.addEventListener("focusout", function(e) {
console.log("失焦:", e.target.name);
});
</script>
const input = document.querySelector("input");
// 聚焦
input.focus();
// 失焦
input.blur();
// autofocus属性
// <input autofocus>
与表单操作相关的事件。
const form = document.querySelector("form");
form.addEventListener("submit", function(e) {
e.preventDefault(); // 阻止默认提交
const formData = new FormData(this);
console.log("表单数据:", Object.fromEntries(formData));
// 手动提交
fetch("/api/submit", {
method: "POST",
body: formData
});
});
const input = document.querySelector("input");
// input - 值改变时触发
input.addEventListener("input", function(e) {
console.log("当前值:", this.value);
console.log("输入数据:", e.data);
});
// 实时搜索
const searchInput = document.querySelector("#search");
searchInput.addEventListener("input", debounce(function() {
search(this.value);
}, 300));
// change - 值改变并失去焦点时触发
input.addEventListener("change", function(e) {
console.log("值已改变:", this.value);
});
// select - 选中文本时触发
input.addEventListener("select", function(e) {
console.log("选中:", this.value.substring(
this.selectionStart,
this.selectionEnd
));
});
// input: 每次输入都触发
// change: 失去焦点且值改变时触发
const input = document.querySelector("input");
input.addEventListener("input", function() {
console.log("input:", this.value); // 实时
});
input.addEventListener("change", function() {
console.log("change:", this.value); // 完成后
});
与滚动相关的事件。
// 监听页面滚动
window.addEventListener("scroll", function() {
const scrollY = window.scrollY;
const docHeight = document.documentElement.scrollHeight;
const winHeight = window.innerHeight;
// 滚动到底部
if (scrollY + winHeight >= docHeight - 100) {
loadMore();
}
// 显示回到顶部按钮
const backToTop = document.querySelector("#backToTop");
backToTop.style.display = scrollY > 300 ? "block" : "none";
});
const container = document.querySelector(".scroll-container");
container.addEventListener("scroll", function() {
console.log("滚动位置:", this.scrollTop);
// 滚动到底部
if (this.scrollTop + this.clientHeight >= this.scrollHeight) {
console.log("到达底部");
}
});
// 使用节流
let ticking = false;
window.addEventListener("scroll", function() {
if (!ticking) {
requestAnimationFrame(function() {
updateScrollPosition();
ticking = false;
});
ticking = true;
}
});
// 使用passive提升性能
window.addEventListener("scroll", function() {
// 不会调用preventDefault
}, { passive: true });
移动设备上的触摸事件。
const element = document.querySelector(".touch-area");
// touchstart - 触摸开始
element.addEventListener("touchstart", function(e) {
console.log("触摸开始");
console.log("触摸点数量:", e.touches.length);
console.log("触摸位置:", e.touches[0].clientX, e.touches[0].clientY);
});
// touchmove - 触摸移动
element.addEventListener("touchmove", function(e) {
e.preventDefault(); // 阻止滚动
console.log("触摸移动");
});
// touchend - 触摸结束
element.addEventListener("touchend", function(e) {
console.log("触摸结束");
});
// touchcancel - 触摸取消
element.addEventListener("touchcancel", function(e) {
console.log("触摸取消");
});
element.addEventListener("touchstart", function(e) {
// touches - 当前所有触摸点
console.log("所有触摸点:", e.touches);
// targetTouches - 当前元素上的触摸点
console.log("元素触摸点:", e.targetTouches);
// changedTouches - 触发事件的触摸点
console.log("改变的触摸点:", e.changedTouches);
// 获取第一个触摸点
const touch = e.touches[0];
console.log("位置:", touch.clientX, touch.clientY);
console.log("标识:", touch.identifier);
});
let startX, startY;
element.addEventListener("touchstart", function(e) {
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
});
element.addEventListener("touchend", function(e) {
const endX = e.changedTouches[0].clientX;
const endY = e.changedTouches[0].clientY;
const diffX = endX - startX;
const diffY = endY - startY;
// 判断滑动方向
if (Math.abs(diffX) > Math.abs(diffY)) {
if (diffX > 50) {
console.log("向右滑动");
} else if (diffX < -50) {
console.log("向左滑动");
}
} else {
if (diffY > 50) {
console.log("向下滑动");
} else if (diffY < -50) {
console.log("向上滑动");
}
}
});
HTML5拖放API相关事件。
const draggable = document.querySelector(".draggable");
const dropzone = document.querySelector(".dropzone");
// 被拖动元素的事件
draggable.addEventListener("dragstart", function(e) {
console.log("开始拖动");
e.dataTransfer.setData("text/plain", this.id);
e.dataTransfer.effectAllowed = "move";
});
draggable.addEventListener("drag", function(e) {
// 持续触发
});
draggable.addEventListener("dragend", function(e) {
console.log("拖动结束");
});
// 放置目标的事件
dropzone.addEventListener("dragenter", function(e) {
e.preventDefault();
this.classList.add("drag-over");
});
dropzone.addEventListener("dragover", function(e) {
e.preventDefault(); // 必须阻止默认行为
});
dropzone.addEventListener("dragleave", function(e) {
this.classList.remove("drag-over");
});
dropzone.addEventListener("drop", function(e) {
e.preventDefault();
this.classList.remove("drag-over");
const id = e.dataTransfer.getData("text/plain");
const element = document.getElementById(id);
this.appendChild(element);
});
element.addEventListener("dragstart", function(e) {
// 设置数据
e.dataTransfer.setData("text/plain", "文本数据");
e.dataTransfer.setData("text/uri-list", "http://example.com");
e.dataTransfer.setData("application/json", JSON.stringify(data));
// 设置效果
e.dataTransfer.effectAllowed = "copy"; // copy, move, link, all, none
// 设置自定义图片
const img = new Image();
img.src = "drag-image.png";
e.dataTransfer.setDragImage(img, 0, 0);
});
dropzone.addEventListener("drop", function(e) {
// 获取数据
const text = e.dataTransfer.getData("text/plain");
// 获取文件
const files = e.dataTransfer.files;
// 检查效果
console.log(e.dataTransfer.dropEffect);
});
与剪贴板操作相关的事件。
const input = document.querySelector("input");
// copy - 复制
input.addEventListener("copy", function(e) {
console.log("复制");
// 可以修改剪贴板内容
e.clipboardData.setData("text/plain", "自定义内容");
e.preventDefault();
});
// cut - 剪切
input.addEventListener("cut", function(e) {
console.log("剪切");
});
// paste - 粘贴
input.addEventListener("paste", function(e) {
console.log("粘贴");
// 获取剪贴板数据
const text = e.clipboardData.getData("text/plain");
console.log("粘贴内容:", text);
// 可以阻止粘贴
// e.preventDefault();
});
// 现代异步API
async function copyText(text) {
try {
await navigator.clipboard.writeText(text);
console.log("复制成功");
} catch (err) {
console.error("复制失败:", err);
}
}
async function pasteText() {
try {
const text = await navigator.clipboard.readText();
console.log("粘贴内容:", text);
return text;
} catch (err) {
console.error("粘贴失败:", err);
}
}
// 使用
copyText("东巴文 db-w.cn");
pasteText().then(text => console.log(text));
与音视频相关的事件。
const video = document.querySelector("video");
const audio = document.querySelector("audio");
// 加载事件
video.addEventListener("loadstart", () => console.log("开始加载"));
video.addEventListener("loadedmetadata", () => console.log("元数据加载完成"));
video.addEventListener("loadeddata", () => console.log("数据加载完成"));
video.addEventListener("canplay", () => console.log("可以播放"));
video.addEventListener("canplaythrough", () => console.log("可以流畅播放"));
// 播放事件
video.addEventListener("play", () => console.log("开始播放"));
video.addEventListener("pause", () => console.log("暂停"));
video.addEventListener("playing", () => console.log("正在播放"));
video.addEventListener("ended", () => console.log("播放结束"));
video.addEventListener("timeupdate", () => {
console.log("当前时间:", video.currentTime);
});
// 错误事件
video.addEventListener("error", function(e) {
console.error("加载错误:", e);
});
// 音量事件
video.addEventListener("volumechange", () => {
console.log("音量:", video.volume);
});
const video = document.querySelector("video");
// 播放控制
video.play(); // 播放
video.pause(); // 暂停
// 时间控制
video.currentTime = 30; // 跳转到30秒
// 音量控制
video.volume = 0.5; // 50%音量
video.muted = true; // 静音
// 播放速度
video.playbackRate = 2; // 2倍速
// 全屏
video.requestFullscreen();
掌握了事件类型后,让我们继续学习:
东巴文(db-w.cn) - 让编程学习更简单
🎯 东巴文寄语:JavaScript提供了丰富的事件类型,从鼠标键盘到触摸拖放,从表单提交到媒体播放,掌握这些事件类型是构建交互式应用的基础。在 db-w.cn,我们帮你全面掌握事件处理!