事件类型

UI事件

与浏览器窗口相关的事件。

load事件

// 页面加载完成
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);

DOMContentLoaded事件

// DOM解析完成(不等图片等资源)
document.addEventListener("DOMContentLoaded", function() {
    console.log("DOM已就绪");
    // 可以安全操作DOM
});

// 比load更早触发
// DOMContentLoaded → load

unload事件

// 页面卸载时
window.addEventListener("unload", function() {
    // 发送统计数据
    navigator.sendBeacon("/analytics", data);
});

// beforeunload - 可以提示用户
window.addEventListener("beforeunload", function(e) {
    e.preventDefault();
    e.returnValue = "确定离开吗?";
});

resize事件

// 窗口大小改变
window.addEventListener("resize", function() {
    console.log("窗口大小:", window.innerWidth, window.innerHeight);
});

// 使用防抖优化
let resizeTimer;
window.addEventListener("resize", function() {
    clearTimeout(resizeTimer);
    resizeTimer = setTimeout(function() {
        console.log("调整完成");
    }, 200);
});

scroll事件

// 页面滚动
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>

focus方法

const input = document.querySelector("input");

// 聚焦
input.focus();

// 失焦
input.blur();

// autofocus属性
// <input autofocus>

表单事件

与表单操作相关的事件。

submit事件

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
    });
});

input事件

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事件

// 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对比

// 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);
});

DataTransfer对象

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

// 现代异步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();

下一步

掌握了事件类型后,让我们继续学习:

  1. 事件高级 - 学习高级事件处理
  2. Window对象 - 学习BOM基础
  3. Location对象 - 学习URL操作

东巴文(db-w.cn) - 让编程学习更简单

🎯 东巴文寄语:JavaScript提供了丰富的事件类型,从鼠标键盘到触摸拖放,从表单提交到媒体播放,掌握这些事件类型是构建交互式应用的基础。在 db-w.cn,我们帮你全面掌握事件处理!