jQuery事件处理详解

事件是用户与网页交互时发生的事情。jQuery提供了一套强大的事件处理API,使得绑定和处理事件变得简单而高效。

事件处理概述

事件处理是Web开发的核心部分,它允许网页对用户的交互做出响应。jQuery简化了事件处理,提供了跨浏览器兼容的解决方案。

鼠标事件
  • click - 点击事件
  • dblclick - 双击事件
  • mouseenter - 鼠标进入
  • mouseleave - 鼠标离开
  • mousemove - 鼠标移动
键盘事件
  • keydown - 键按下
  • keyup - 键释放
  • keypress - 键按下(字符键)
表单事件
  • focus - 获得焦点
  • blur - 失去焦点
  • change - 值改变
  • submit - 表单提交
窗口事件
  • load - 加载完成
  • resize - 调整大小
  • scroll - 滚动事件
重要概念
  1. 事件绑定: 将事件处理函数附加到元素
  2. 事件对象: 事件发生时创建的包含事件信息的对象
  3. 事件冒泡: 事件从目标元素向上传播到文档根元素
  4. 事件委托: 将事件处理程序附加到父元素,处理子元素的事件
  5. 事件命名空间: 为事件添加命名空间以便管理

事件绑定方法

jQuery提供了多种事件绑定方法,每种方法都有其适用场景。

on() 方法

jQuery 1.7+ 推荐的事件绑定方法,功能最强大,支持所有事件类型。

// 基本语法
$(selector).on(events[, selector][, data], handler)

// 绑定单个事件
$(selector).on("click", function() {})

// 绑定多个事件
$(selector).on("click mouseenter", function() {})

// 带事件委托
$(parent).on("click", childSelector, function() {})

// 传递数据
$(selector).on("click", {key: value}, function(event) {})
示例:
// 绑定点击事件
$("#button").on("click", function() {
    alert("按钮被点击了!");
});

// 绑定多个事件
$("#element").on("mouseenter mouseleave", function(event) {
    if (event.type === "mouseenter") {
        $(this).css("background-color", "yellow");
    } else {
        $(this).css("background-color", "white");
    }
});

// 事件委托(处理动态添加的元素)
$("#list").on("click", "li", function() {
    alert("列表项被点击: " + $(this).text());
});

// 传递数据给事件处理函数
$("#button").on("click", {name: "张三", age: 25}, function(event) {
    console.log("数据:", event.data); // {name: "张三", age: 25}
});

// 使用命名空间
$("#element").on("click.myNamespace", function() {
    console.log("带命名空间的点击事件");
});

// 一次性事件
$("#button").one("click", function() {
    alert("这个按钮只能点击一次!");
});
on() 方法的优势
  • 统一的事件绑定API
  • 支持事件委托
  • 支持事件命名空间
  • 可以传递数据给处理函数
  • 支持一次性事件(通过one()方法)

off() 方法

移除通过 on() 方法绑定的事件处理程序。

// 移除所有事件处理程序
$(selector).off()

// 移除特定类型的事件
$(selector).off("click")

// 移除特定处理函数
$(selector).off("click", handler)

// 移除特定命名空间的事件
$(selector).off(".myNamespace")

// 移除事件委托
$(parent).off("click", childSelector)
示例:
// 定义事件处理函数
function handleClick() {
    console.log("按钮被点击");
}

// 绑定事件
$("#button").on("click", handleClick);

// 移除事件
$("#button").off("click", handleClick);

// 绑定多个事件
$("#element").on("click mouseenter", function() {
    console.log("事件触发");
});

// 移除所有click事件
$("#element").off("click");

// 移除所有事件
$("#element").off();

// 使用命名空间
$("#element").on("click.myNamespace", function() {
    console.log("命名空间事件");
});

// 移除特定命名空间的事件
$("#element").off(".myNamespace");

// 事件委托的移除
$("#list").on("click", "li", function() {
    console.log("列表项点击");
});

// 移除事件委托
$("#list").off("click", "li");

// 移除特定处理函数的事件委托
function handleListItemClick() {
    console.log("列表项点击");
}
$("#list").on("click", "li", handleListItemClick);
$("#list").off("click", "li", handleListItemClick);

trigger() 方法

触发绑定到元素的事件处理程序。

// 触发事件
$(selector).trigger(eventType[, extraParameters])

// 触发自定义事件
$(selector).trigger("customEvent")

// 传递额外参数
$(selector).trigger("click", [param1, param2])
示例:
// 绑定点击事件
$("#button").on("click", function(event, param1, param2) {
    console.log("按钮被点击", param1, param2);
});

// 触发点击事件
$("#button").trigger("click");

// 触发事件并传递参数
$("#button").trigger("click", ["参数1", "参数2"]);

// 触发自定义事件
$("#element").on("myCustomEvent", function() {
    console.log("自定义事件被触发");
});
$("#element").trigger("myCustomEvent");

// 触发多个事件
$("#element").on("event1 event2", function(event) {
    console.log(event.type + " 被触发");
});
$("#element").trigger("event1 event2");

// 触发表单提交事件
$("#form").trigger("submit");

// 触发带命名空间的事件
$("#element").on("click.myNamespace", function() {
    console.log("命名空间事件");
});
$("#element").trigger("click.myNamespace");

快捷方法

jQuery为常用事件提供了快捷方法,语法更简洁。

// 点击事件
$(selector).click(handler)

// 鼠标进入事件
$(selector).mouseenter(handler)

// 键盘按下事件
$(selector).keydown(handler)

// 聚焦事件
$(selector).focus(handler)

// 加载事件
$(window).load(handler)
示例:
// 快捷方法绑定事件
$("#button").click(function() {
    alert("按钮被点击");
});

$("#input").focus(function() {
    $(this).css("border-color", "blue");
});

$("#input").blur(function() {
    $(this).css("border-color", "#ccc");
});

$("#element").mouseenter(function() {
    $(this).css("background-color", "yellow");
}).mouseleave(function() {
    $(this).css("background-color", "white");
});

// 快捷方法触发事件
$("#button").click(); // 触发点击事件

$("#input").focus(); // 触发聚焦事件

// 快捷方法移除事件
$("#button").off("click"); // 只能这样移除,没有.unclick()方法

// 注意:快捷方法内部也是调用on()方法
// 以下两行代码是等价的:
$("#button").click(function() {});
$("#button").on("click", function() {});
事件绑定方法对比
方法 描述 版本 推荐度
on() 统一的事件绑定方法,功能最全 1.7+ ★★★★★
off() 移除通过on()绑定的事件 1.7+ ★★★★★
bind() 旧版事件绑定方法(已过时) 1.0-3.0 ★☆☆☆☆
unbind() 旧版事件移除方法(已过时) 1.0-3.0 ★☆☆☆☆
delegate() 旧版事件委托方法(已过时) 1.4.2-3.0 ★☆☆☆☆
undelegate() 旧版事件委托移除(已过时) 1.4.2-3.0 ★☆☆☆☆
快捷方法 click(), mouseenter()等 1.0+ ★★★★☆

鼠标事件

鼠标事件在用户使用鼠标与元素交互时触发。

click

点击事件(按下并释放鼠标按钮)

$("#element").click(function() {
    console.log("元素被点击");
});
dblclick

双击事件

$("#element").dblclick(function() {
    console.log("元素被双击");
});
mousedown

鼠标按钮按下

$("#element").mousedown(function(event) {
    console.log("按钮按下:", event.which);
});
mouseup

鼠标按钮释放

$("#element").mouseup(function() {
    console.log("按钮释放");
});
mouseenter

鼠标进入元素区域

$("#element").mouseenter(function() {
    $(this).addClass("hover");
});
mouseleave

鼠标离开元素区域

$("#element").mouseleave(function() {
    $(this).removeClass("hover");
});
mouseover

鼠标移动到元素上(会冒泡)

$("#element").mouseover(function() {
    console.log("mouseover");
});
mouseout

鼠标移出元素(会冒泡)

$("#element").mouseout(function() {
    console.log("mouseout");
});
mousemove

鼠标在元素上移动

$("#element").mousemove(function(event) {
    console.log("位置:", event.pageX, event.pageY);
});
contextmenu

右键菜单事件

$("#element").contextmenu(function(event) {
    event.preventDefault(); // 阻止默认右键菜单
    showCustomMenu();
});

鼠标事件综合示例

展示鼠标事件的常见用法和事件对象属性。

// 鼠标事件综合示例
$("#demo-element")
    // 点击事件
    .on("click", function(event) {
        console.log("点击事件");
        console.log("鼠标按钮:", event.which); // 1=左键, 2=中键, 3=右键
        console.log("坐标:", event.pageX, event.pageY);
        console.log("目标元素:", event.target.tagName);
    })
    // 双击事件
    .on("dblclick", function() {
        console.log("双击事件");
        $(this).toggleClass("highlight");
    })
    // 鼠标进入/离开
    .on("mouseenter mouseleave", function(event) {
        if (event.type === "mouseenter") {
            $(this).css("border-color", "#3498db");
        } else {
            $(this).css("border-color", "#ddd");
        }
    })
    // 鼠标移动
    .on("mousemove", function(event) {
        $("#coords").text(event.pageX + ", " + event.pageY);
    })
    // 鼠标按下/释放
    .on("mousedown mouseup", function(event) {
        if (event.type === "mousedown") {
            $(this).css("background-color", "#e74c3c");
        } else {
            $(this).css("background-color", "#3498db");
        }
        console.log("按钮:", event.which);
    })
    // 右键菜单
    .on("contextmenu", function(event) {
        event.preventDefault();
        alert("自定义右键菜单");
        return false;
    });

// 获取鼠标位置
$(document).on("mousemove", function(event) {
    // event.pageX/Y: 相对于文档的坐标
    // event.clientX/Y: 相对于视口的坐标
    // event.screenX/Y: 相对于屏幕的坐标
    console.log("文档坐标:", event.pageX, event.pageY);
    console.log("视口坐标:", event.clientX, event.clientY);
    console.log("屏幕坐标:", event.screenX, event.screenY);
});

// 鼠标事件对象属性示例
$("#element").on("click", function(event) {
    console.log("事件类型:", event.type); // "click"
    console.log("时间戳:", event.timeStamp); // 事件发生的时间戳
    console.log("目标元素:", event.target); // 触发事件的元素
    console.log("当前元素:", event.currentTarget); // 绑定事件处理程序的元素
    console.log("是否按下了Shift键:", event.shiftKey);
    console.log("是否按下了Ctrl键:", event.ctrlKey);
    console.log("是否按下了Alt键:", event.altKey);
    console.log("是否按下了Meta键:", event.metaKey);
    console.log("鼠标按钮:", event.button); // 0=左键, 1=中键, 2=右键
    console.log("相关元素:", event.relatedTarget); // 对于mouseenter/mouseleave事件
});
鼠标事件演示:
在此区域移动、点击鼠标
事件日志:
mouseenter/mouseleave vs mouseover/mouseout
特性 mouseenter/mouseleave mouseover/mouseout
事件冒泡 不会冒泡 会冒泡
触发频率 进入/离开元素时触发一次 进入/离开元素及其子元素时都会触发
推荐场景 鼠标悬停效果 需要事件冒泡的场景
jQuery版本 1.0+ 1.0+
示例
$("#parent").mouseenter(function() {
    // 只在鼠标进入父元素时触发
});
$("#parent").mouseover(function() {
    // 鼠标进入父元素或子元素都会触发
});

键盘事件

键盘事件在用户按下或释放键盘按键时触发。

keydown

键按下时触发(任何键)

$("#input").keydown(function(event) {
    console.log("键按下:", event.key);
});
keyup

键释放时触发

$("#input").keyup(function(event) {
    console.log("键释放:", event.key);
});
keypress

字符键按下时触发

$("#input").keypress(function(event) {
    console.log("字符键:", event.which);
});

键盘事件综合示例

展示键盘事件的常见用法和事件对象属性。

// 键盘事件综合示例
$("#text-input").on({
    // keydown - 键按下
    keydown: function(event) {
        console.log("keydown - 键码:", event.keyCode);
        console.log("键:", event.key);
        console.log("是否Ctrl键:", event.ctrlKey);

        // 检测特定按键
        if (event.keyCode === 13) { // Enter键
            console.log("Enter键被按下");
            event.preventDefault(); // 阻止默认行为
        }

        if (event.keyCode === 27) { // ESC键
            console.log("ESC键被按下");
            $(this).blur();
        }

        // 组合键检测
        if (event.ctrlKey && event.keyCode === 83) { // Ctrl+S
            event.preventDefault();
            saveContent();
        }
    },

    // keyup - 键释放
    keyup: function(event) {
        console.log("keyup - 键:", event.key);

        // 实时显示输入长度
        var length = $(this).val().length;
        $("#char-count").text(length);
    },

    // keypress - 字符键按下
    keypress: function(event) {
        console.log("keypress - 字符码:", event.which);

        // 限制只能输入数字
        if (!/[0-9]/.test(String.fromCharCode(event.which))) {
            event.preventDefault();
        }
    }
});

// 全局键盘事件
$(document).on("keydown", function(event) {
    // 快捷键支持
    switch(event.keyCode) {
        case 37: // 左箭头
            navigateLeft();
            break;
        case 39: // 右箭头
            navigateRight();
            break;
        case 38: // 上箭头
            navigateUp();
            break;
        case 40: // 下箭头
            navigateDown();
            break;
    }
});

// 键盘事件对象属性
$("#input").on("keydown", function(event) {
    console.log("事件类型:", event.type); // "keydown"
    console.log("键码:", event.keyCode); // 按键的键码
    console.log("字符码:", event.which); // 字符码(已弃用,但jQuery标准化)
    console.log("键:", event.key); // 按键的字符串表示(推荐)
    console.log("代码:", event.code); // 物理按键代码
    console.log("是否重复:", event.repeat); // 是否按住不放
    console.log("是否Shift键:", event.shiftKey);
    console.log("是否Ctrl键:", event.ctrlKey);
    console.log("是否Alt键:", event.altKey);
    console.log("是否Meta键:", event.metaKey);
    console.log("是否大写锁定:", event.capsLock);
    console.log("是否数字锁定:", event.numLock);

    // 阻止默认行为
    if (event.key === "Escape") {
        event.preventDefault();
        $(this).val("");
    }
});

// 常用键码
var keyCodes = {
    ENTER: 13,
    ESC: 27,
    SPACE: 32,
    LEFT: 37,
    UP: 38,
    RIGHT: 39,
    DOWN: 40,
    TAB: 9,
    BACKSPACE: 8,
    DELETE: 46,
    HOME: 36,
    END: 35,
    PAGE_UP: 33,
    PAGE_DOWN: 34,
    F1: 112,
    F12: 123
};

// 检测组合键
$(document).on("keydown", function(event) {
    // Ctrl + C
    if (event.ctrlKey && event.key === "c") {
        console.log("复制");
    }

    // Ctrl + V
    if (event.ctrlKey && event.key === "v") {
        console.log("粘贴");
    }

    // Ctrl + Z
    if (event.ctrlKey && event.key === "z") {
        console.log("撤销");
        event.preventDefault();
    }

    // Alt + 键
    if (event.altKey && event.key === "s") {
        console.log("Alt+S 保存");
        event.preventDefault();
    }
});
键盘事件演示:
字符数: 0 最后按键: 键码: -
事件日志:
键盘事件对比
事件 触发时机 支持的键 推荐用途
keydown 键按下时 所有键 检测功能键、快捷键
keyup 键释放时 所有键 完成输入、检测键释放
keypress 字符键按下时 字符键(a-z, 0-9等) 字符输入处理(已弃用)

表单事件

表单事件在表单元素与用户交互时触发。

focus

元素获得焦点时触发

$("input").focus(function() {
    $(this).addClass("focused");
});
blur

元素失去焦点时触发

$("input").blur(function() {
    validateField(this);
});
change

元素值改变并失去焦点时触发

$("select").change(function() {
    updateSelection($(this).val());
});
input

元素值改变时立即触发

$("textarea").on("input", function() {
    updateCharCount($(this).val());
});
submit

表单提交时触发

$("form").submit(function(event) {
    if (!validateForm()) {
        event.preventDefault();
    }
});
select

文本被选择时触发

$("input[type='text']").select(function() {
    console.log("文本被选择");
});

表单事件综合示例

展示表单事件的常见用法和表单验证。

// 表单事件综合示例
$("#myForm").on({
    // 提交事件
    submit: function(event) {
        event.preventDefault(); // 阻止默认提交

        if (validateForm()) {
            // 验证通过,手动提交
            console.log("表单提交:", $(this).serialize());

            // Ajax提交
            $.ajax({
                url: $(this).attr("action"),
                method: $(this).attr("method"),
                data: $(this).serialize(),
                success: function(response) {
                    console.log("提交成功:", response);
                }
            });
        } else {
            console.log("表单验证失败");
        }
    },

    // 重置事件
    reset: function() {
        console.log("表单被重置");
        $(".error-message").hide();
    }
});

// 输入框事件
$("#username")
    // 获得焦点
    .focus(function() {
        $(this).css("border-color", "#3498db");
        $("#username-help").show();
    })
    // 失去焦点
    .blur(function() {
        $(this).css("border-color", "#ddd");
        $("#username-help").hide();

        // 验证用户名
        validateUsername($(this).val());
    })
    // 输入时实时验证
    .on("input", function() {
        var value = $(this).val();
        $("#username-length").text(value.length);

        if (value.length > 0 && value.length < 3) {
            showError($(this), "用户名至少3个字符");
        } else {
            clearError($(this));
        }
    })
    // 值改变(失去焦点后)
    .change(function() {
        console.log("用户名改变为:", $(this).val());
    });

// 下拉框事件
$("#country")
    .change(function() {
        var country = $(this).val();
        console.log("选择的国家:", country);

        // 动态加载城市
        loadCities(country);
    });

// 复选框事件
$("input[type='checkbox']")
    .change(function() {
        var isChecked = $(this).prop("checked");
        console.log("复选框状态:", isChecked);

        // 更新选中计数
        var checkedCount = $("input[type='checkbox']:checked").length;
        $("#selected-count").text(checkedCount);
    });

// 单选框事件
$("input[type='radio']")
    .change(function() {
        var value = $(this).val();
        console.log("选择的值:", value);
    });

// 表单验证函数
function validateForm() {
    var isValid = true;

    // 验证用户名
    if ($("#username").val().trim() === "") {
        showError($("#username"), "用户名不能为空");
        isValid = false;
    }

    // 验证邮箱
    var email = $("#email").val();
    var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    if (!emailRegex.test(email)) {
        showError($("#email"), "邮箱格式不正确");
        isValid = false;
    }

    // 验证密码
    var password = $("#password").val();
    if (password.length < 6) {
        showError($("#password"), "密码至少6个字符");
        isValid = false;
    }

    return isValid;
}

function showError($element, message) {
    $element.css("border-color", "#e74c3c");
    $element.next(".error-message").remove();
    $element.after('
' + message + '
'); } function clearError($element) { $element.css("border-color", "#ddd"); $element.next(".error-message").remove(); } // 获取表单数据 $("#submit-btn").click(function() { // 序列化表单数据 var formData = $("#myForm").serialize(); console.log("表单数据:", formData); // 序列化为数组 var formArray = $("#myForm").serializeArray(); console.log("表单数组:", formArray); // 获取特定字段值 var username = $("#username").val(); var email = $("#email").val(); var newsletter = $("#newsletter").prop("checked"); // 获取复选框值(多选) var hobbies = []; $("input[name='hobbies']:checked").each(function() { hobbies.push($(this).val()); }); });
表单事件演示:
用户名长度: 0
事件日志:

窗口事件

窗口事件在浏览器窗口状态改变时触发。

load

页面完全加载后触发

$(window).load(function() {
    console.log("页面完全加载");
});
resize

窗口大小改变时触发

$(window).resize(function() {
    console.log("窗口大小:", $(this).width());
});
scroll

窗口滚动时触发

$(window).scroll(function() {
    console.log("滚动位置:", $(this).scrollTop());
});
unload

页面卸载时触发(已弃用)

$(window).on("unload", function() {
    // 清理工作
});
beforeunload

页面卸载前触发

$(window).on("beforeunload", function() {
    return "确定离开页面吗?";
});

窗口事件综合示例

展示窗口事件的常见用法和响应式设计。

// 窗口事件综合示例
$(window)
    // 页面加载完成
    .on("load", function() {
        console.log("页面加载完成");

        // 初始化操作
        initPage();

        // 隐藏加载动画
        $("#loading").fadeOut();
    })

    // 窗口大小改变
    .on("resize", function() {
        var width = $(this).width();
        var height = $(this).height();

        console.log("窗口尺寸:", width + "x" + height);

        // 响应式设计
        if (width < 768) {
            $("body").addClass("mobile").removeClass("desktop");
        } else {
            $("body").addClass("desktop").removeClass("mobile");
        }

        // 调整布局
        adjustLayout(width);
    })

    // 窗口滚动
    .on("scroll", function() {
        var scrollTop = $(this).scrollTop();
        var windowHeight = $(this).height();
        var documentHeight = $(document).height();

        console.log("滚动位置:", scrollTop);

        // 滚动到顶部按钮
        if (scrollTop > 300) {
            $("#back-to-top").fadeIn();
        } else {
            $("#back-to-top").fadeOut();
        }

        // 无限滚动
        if (scrollTop + windowHeight >= documentHeight - 100) {
            loadMoreContent();
        }

        // 视差滚动效果
        $(".parallax").css("transform", "translateY(" + scrollTop * 0.5 + "px)");

        // 固定导航栏
        if (scrollTop > $("#header").height()) {
            $("#navbar").addClass("fixed");
        } else {
            $("#navbar").removeClass("fixed");
        }
    });

// 页面加载状态
$(document).ready(function() {
    console.log("DOM准备就绪");

    // DOM操作可以在这里进行
    $("#content").html("页面已加载");
});

// 注意:$(document).ready() vs $(window).load()
// ready: DOM加载完成,图片等资源可能还没加载
// load: 所有资源(图片、样式等)都加载完成

// 页面卸载前
$(window).on("beforeunload", function(event) {
    // 如果有未保存的数据
    if (hasUnsavedChanges()) {
        var message = "您有未保存的更改,确定要离开吗?";
        event.returnValue = message; // 标准方法
        return message; // 兼容旧浏览器
    }
});

// 页面卸载
$(window).on("unload", function() {
    // 清理工作(注意:限制很多)
    // 可以发送一个同步的Ajax请求
    // 但更推荐使用visibilitychange事件
});

// 页面可见性API
$(document).on("visibilitychange", function() {
    if (document.hidden) {
        console.log("页面被隐藏");
        // 暂停视频、动画等
    } else {
        console.log("页面可见");
        // 恢复视频、动画等
    }
});

// 获取窗口信息
function getWindowInfo() {
    return {
        width: $(window).width(),      // 视口宽度
        height: $(window).height(),    // 视口高度
        scrollTop: $(window).scrollTop(), // 垂直滚动位置
        scrollLeft: $(window).scrollLeft(), // 水平滚动位置
        screenWidth: screen.width,     // 屏幕宽度
        screenHeight: screen.height,   // 屏幕高度
        devicePixelRatio: window.devicePixelRatio // 设备像素比
    };
}

// 响应式断点检测
function checkBreakpoint() {
    var width = $(window).width();

    if (width >= 1200) {
        return "xl"; // 特大屏幕
    } else if (width >= 992) {
        return "lg"; // 大屏幕
    } else if (width >= 768) {
        return "md"; // 中等屏幕
    } else if (width >= 576) {
        return "sm"; // 小屏幕
    } else {
        return "xs"; // 超小屏幕
    }
}

// 监听断点变化
var currentBreakpoint = checkBreakpoint();
$(window).on("resize", function() {
    var newBreakpoint = checkBreakpoint();

    if (newBreakpoint !== currentBreakpoint) {
        console.log("断点变化:", currentBreakpoint, "->", newBreakpoint);
        currentBreakpoint = newBreakpoint;

        // 执行断点相关的操作
        onBreakpointChange(newBreakpoint);
    }
});
窗口事件演示:
窗口信息
宽度: -px
高度: -px
滚动位置: -px
屏幕尺寸: -
断点: -

滚动此区域查看滚动事件

加载中...

继续滚动...

事件日志:

触摸事件

触摸事件在触摸屏设备上与元素交互时触发。

touchstart

触摸开始时触发

$("#element").on("touchstart", function(event) {
    console.log("触摸开始");
});
touchmove

触摸移动时触发

$("#element").on("touchmove", function(event) {
    event.preventDefault();
});
touchend

触摸结束时触发

$("#element").on("touchend", function(event) {
    console.log("触摸结束");
});
touchcancel

触摸被取消时触发

$("#element").on("touchcancel", function(event) {
    console.log("触摸取消");
});

触摸事件综合示例

展示触摸事件的常见用法和移动端手势识别。

// 触摸事件综合示例
var touchStartX = 0;
var touchStartY = 0;
var touchEndX = 0;
var touchEndY = 0;

$("#touch-element")
    // 触摸开始
    .on("touchstart", function(event) {
        event.preventDefault();

        var touch = event.originalEvent.touches[0];
        touchStartX = touch.pageX;
        touchStartY = touch.pageY;

        console.log("触摸开始:", touchStartX, touchStartY);
        $(this).addClass("touching");

        // 记录触摸时间
        $(this).data("touchStartTime", Date.now());
    })

    // 触摸移动
    .on("touchmove", function(event) {
        event.preventDefault();

        var touch = event.originalEvent.touches[0];
        var currentX = touch.pageX;
        var currentY = touch.pageY;

        console.log("触摸移动:", currentX, currentY);

        // 计算移动距离
        var deltaX = currentX - touchStartX;
        var deltaY = currentY - touchStartY;

        // 拖拽效果
        $(this).css({
            transform: "translate(" + deltaX + "px, " + deltaY + "px)"
        });
    })

    // 触摸结束
    .on("touchend", function(event) {
        event.preventDefault();

        var touch = event.originalEvent.changedTouches[0];
        touchEndX = touch.pageX;
        touchEndY = touch.pageY;

        console.log("触摸结束:", touchEndX, touchEndY);
        $(this).removeClass("touching");

        // 检测手势
        detectGesture();

        // 恢复位置
        $(this).css({
            transform: "translate(0, 0)",
            transition: "transform 0.3s"
        });

        // 移除过渡效果
        setTimeout(function() {
            $("#touch-element").css("transition", "none");
        }, 300);
    })

    // 触摸取消
    .on("touchcancel", function(event) {
        console.log("触摸取消");
        $(this).removeClass("touching");
    });

// 手势识别函数
function detectGesture() {
    var deltaX = touchEndX - touchStartX;
    var deltaY = touchEndY - touchStartY;
    var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
    var duration = Date.now() - $("#touch-element").data("touchStartTime");

    console.log("手势参数:", {
        deltaX: deltaX,
        deltaY: deltaY,
        distance: distance,
        duration: duration
    });

    // 滑动检测
    if (Math.abs(deltaX) > 50 && Math.abs(deltaY) < 30) {
        if (deltaX > 0) {
            console.log("向右滑动");
            swipeRight();
        } else {
            console.log("向左滑动");
            swipeLeft();
        }
    }

    // 垂直滑动
    if (Math.abs(deltaY) > 50 && Math.abs(deltaX) < 30) {
        if (deltaY > 0) {
            console.log("向下滑动");
            swipeDown();
        } else {
            console.log("向上滑动");
            swipeUp();
        }
    }

    // 轻触检测(快速触摸)
    if (distance < 10 && duration < 300) {
        console.log("轻触");
        handleTap();
    }

    // 长按检测
    if (duration > 1000) {
        console.log("长按");
        handleLongPress();
    }
}

// 多点触控
$("#multi-touch").on("touchstart", function(event) {
    var touches = event.originalEvent.touches;

    console.log("触摸点数:", touches.length);

    if (touches.length === 2) {
        // 双指手势
        console.log("双指触摸");

        var touch1 = touches[0];
        var touch2 = touches[1];

        // 计算初始距离
        var initialDistance = getDistance(
            touch1.pageX, touch1.pageY,
            touch2.pageX, touch2.pageY
        );

        $(this).data("initialDistance", initialDistance);
    }
});

$("#multi-touch").on("touchmove", function(event) {
    var touches = event.originalEvent.touches;

    if (touches.length === 2) {
        event.preventDefault();

        var touch1 = touches[0];
        var touch2 = touches[1];

        // 计算当前距离
        var currentDistance = getDistance(
            touch1.pageX, touch1.pageY,
            touch2.pageX, touch2.pageY
        );

        var initialDistance = $(this).data("initialDistance");
        var scale = currentDistance / initialDistance;

        console.log("缩放比例:", scale);

        // 应用缩放
        $(this).css("transform", "scale(" + scale + ")");
    }
});

function getDistance(x1, y1, x2, y2) {
    var dx = x2 - x1;
    var dy = y2 - y1;
    return Math.sqrt(dx * dx + dy * dy);
}

// 移动端点击延迟处理
// 使用fastclick库或以下方法
$("#mobile-button").on("touchstart click", function(event) {
    // 阻止触摸事件后的click事件
    if (event.type === "touchstart") {
        $(this).data("touchStarted", true);
    } else if (event.type === "click" && $(this).data("touchStarted")) {
        event.preventDefault();
        event.stopPropagation();
        $(this).removeData("touchStarted");
        return false;
    }

    // 处理点击逻辑
    handleButtonClick();
});

// 检测设备是否支持触摸
function isTouchDevice() {
    return 'ontouchstart' in window ||
           navigator.maxTouchPoints > 0 ||
           navigator.msMaxTouchPoints > 0;
}

if (isTouchDevice()) {
    $("body").addClass("touch-device");
    console.log("触摸设备");
} else {
    $("body").addClass("no-touch");
    console.log("非触摸设备");
}
触摸事件演示:

在此区域触摸/点击

(在移动设备或模拟触摸的设备上效果更好)
开始位置: -
结束位置: -
手势: -
触摸点数: 0
设备类型: 检测中...
事件日志:
移动端开发建议
  • 同时处理触摸和鼠标事件以确保兼容性
  • 使用event.preventDefault()防止触摸时的默认行为(如滚动)
  • 考虑点击延迟问题,可使用FastClick等库
  • 为触摸事件提供视觉反馈
  • 测试不同尺寸的触摸设备和不同操作系统

事件对象

事件对象包含事件相关的所有信息,在事件处理函数中作为参数传递。

事件对象详解

jQuery事件对象是对原生事件对象的封装,提供跨浏览器兼容的属性。

// 事件处理函数接收事件对象
$(selector).on("click", function(event) {
  // 使用事件对象
  console.log(event.type);
})
事件对象常用属性:
属性 描述 示例
type 事件类型(如 "click") event.type
target 触发事件的元素 event.target
currentTarget 当前处理事件的元素 event.currentTarget
relatedTarget 相关元素(如mouseenter的离开元素) event.relatedTarget
pageX/pageY 鼠标相对于文档的坐标 event.pageX
clientX/clientY 鼠标相对于视口的坐标 event.clientX
screenX/screenY 鼠标相对于屏幕的坐标 event.screenX
which 鼠标按钮或键盘键码 event.which
key/keyCode 键盘按键信息 event.key
shiftKey 是否按下了Shift键 event.shiftKey
ctrlKey 是否按下了Ctrl键 event.ctrlKey
altKey 是否按下了Alt键 event.altKey
metaKey 是否按下了Meta键 event.metaKey
timeStamp 事件发生的时间戳 event.timeStamp
data 通过on()方法传递的数据 event.data
result 上一个事件处理函数的返回值 event.result
originalEvent 原始的事件对象 event.originalEvent
事件对象方法:
方法 描述 示例
preventDefault() 阻止事件的默认行为 event.preventDefault()
stopPropagation() 阻止事件冒泡 event.stopPropagation()
stopImmediatePropagation() 阻止事件冒泡并阻止同类型其他处理函数执行 event.stopImmediatePropagation()
isDefaultPrevented() 检查是否调用了preventDefault() event.isDefaultPrevented()
isPropagationStopped() 检查是否调用了stopPropagation() event.isPropagationStopped()
// 事件对象使用示例
$("#element").on("click", function(event) {
    // 获取事件信息
    console.log("事件类型:", event.type);
    console.log("目标元素:", event.target.tagName);
    console.log("当前元素:", event.currentTarget.tagName);
    console.log("鼠标坐标:", event.pageX, event.pageY);
    console.log("时间戳:", event.timeStamp);

    // 检查按键状态
    if (event.shiftKey) {
        console.log("按下了Shift键");
    }

    if (event.ctrlKey) {
        console.log("按下了Ctrl键");
    }

    // 阻止默认行为
    event.preventDefault();

    // 阻止事件冒泡
    event.stopPropagation();

    // 检查方法是否已被调用
    console.log("默认行为已阻止?", event.isDefaultPrevented());
    console.log("事件冒泡已阻止?", event.isPropagationStopped());

    // 访问原始事件对象
    console.log("原始事件:", event.originalEvent);

    // 返回结果(可供后续事件处理函数访问)
    return "处理完成";
});

// 链式事件处理
$("#element")
    .on("click", function(event) {
        console.log("第一个处理函数");
        // 这个返回值可以在event.result中访问
        return "第一个返回值";
    })
    .on("click", function(event) {
        console.log("第二个处理函数");
        console.log("上一个函数的返回值:", event.result); // "第一个返回值"
        return "第二个返回值";
    });

// 使用事件数据
$("#button").on("click", {user: "张三", action: "提交"}, function(event) {
    console.log("用户:", event.data.user); // "张三"
    console.log("操作:", event.data.action); // "提交"
});

// 鼠标事件对象
$("#element").on("mousedown", function(event) {
    console.log("鼠标按钮:", event.which); // 1=左键, 2=中键, 3=右键
    console.log("按钮:", event.button); // 同上
});

// 键盘事件对象
$("#input").on("keydown", function(event) {
    console.log("键码:", event.keyCode);
    console.log("键:", event.key);
    console.log("代码:", event.code);
    console.log("是否重复:", event.repeat);
});
事件对象演示:
点击我查看事件对象信息
事件对象属性:

事件委托

事件委托是将事件处理程序附加到父元素,利用事件冒泡处理子元素的事件。

事件委托详解

事件委托可以提高性能,特别是对于动态添加的元素。

// 基本语法
$(parentSelector).on(eventType, childSelector, handler)

// 示例
$("#list").on("click", "li", function() {
  console.log("列表项被点击");
})
为什么使用事件委托:
// 传统方式 - 直接绑定(不推荐用于动态元素)
$("li").click(function() {
    console.log("列表项点击");
});

// 问题:动态添加的li元素不会有点击事件
$("#list").append("
  • 新项目
  • "); // 这个新li没有点击事件 // 解决方案1 - 每次添加元素后重新绑定(性能差) function addListItem(text) { var $li = $("
  • ").text(text); $("#list").append($li); $li.click(function() { // 为每个新元素绑定事件 console.log("点击:", text); }); } // 解决方案2 - 事件委托(推荐) $("#list").on("click", "li", function() { console.log("点击:", $(this).text()); }); // 现在动态添加的li元素也会触发事件 $("#list").append("
  • 新项目
  • "); // 这个新li也有点击事件
    事件委托的优势:
    // 1. 处理动态添加的元素
    $("#dynamic-list").on("click", "li.item", function() {
        // 即使li.item是动态添加的,也会触发事件
        console.log("动态项目被点击");
    });
    
    // 动态添加元素
    setInterval(function() {
        $("#dynamic-list").append('
  • 新项目' + Date.now() + '
  • '); }, 1000); // 2. 减少事件处理程序数量 // 传统方式:为1000个元素绑定1000个事件处理程序 $("td").click(function() { // 性能差 console.log("单元格点击"); }); // 事件委托:只绑定1个事件处理程序 $("#table").on("click", "td", function() { // 性能好 console.log("单元格点击"); }); // 3. 简化事件管理 $("#container").on({ click: function(event) { var $target = $(event.target); // 根据目标元素执行不同操作 if ($target.is("button.delete")) { deleteItem($target.closest(".item")); } else if ($target.is("button.edit")) { editItem($target.closest(".item")); } else if ($target.is(".item")) { selectItem($target); } }, mouseenter: function(event) { if ($(event.target).is(".item")) { $(event.target).addClass("hover"); } }, mouseleave: function(event) { if ($(event.target).is(".item")) { $(event.target).removeClass("hover"); } } }, ".item, button"); // 只代理.item和button元素的事件 // 4. 内存管理更简单 // 移除元素时不需要特别处理事件 $(".item").remove(); // 事件处理程序仍然在#container上 // 如果要移除所有事件,只需: $("#container").off();
    事件委托示例:
    // 表格行操作
    $("#data-table").on("click", "td", function(event) {
        event.stopPropagation(); // 阻止事件冒泡到tr
    
        var $td = $(this);
        var columnIndex = $td.index();
        var rowIndex = $td.closest("tr").index();
    
        console.log("点击单元格:", rowIndex, columnIndex);
    
        // 根据不同列执行不同操作
        if (columnIndex === 0) {
            toggleCheckbox($td);
        } else if (columnIndex === 1) {
            editCell($td);
        } else if (columnIndex === 2) {
            deleteRow($td.closest("tr"));
        }
    });
    
    // 列表操作
    $("#todo-list").on({
        click: function(event) {
            var $target = $(event.target);
    
            if ($target.is(".delete-btn")) {
                // 删除项目
                $target.closest(".todo-item").remove();
            } else if ($target.is(".edit-btn")) {
                // 编辑项目
                editTodoItem($target.closest(".todo-item"));
            } else if ($target.is(".todo-item")) {
                // 切换完成状态
                $target.toggleClass("completed");
            }
        },
        dblclick: function(event) {
            if ($(event.target).is(".todo-text")) {
                // 双击文本编辑
                editTodoText($(event.target));
            }
        }
    }, ".todo-item, .delete-btn, .edit-btn, .todo-text");
    
    // 表单动态字段
    $("#dynamic-form").on({
        focus: function() {
            $(this).addClass("focused");
        },
        blur: function() {
            $(this).removeClass("focused");
            validateField($(this));
        },
        change: function() {
            updateFormState();
        }
    }, "input, select, textarea"); // 代理所有表单元素
    
    // 动态添加表单字段
    $("#add-field").click(function() {
        var fieldId = "field-" + Date.now();
        $("#dynamic-form").append(
            '
    ' + ' ' + ' ' + '
    ' ); }); // 删除动态字段(也需要事件委托) $("#dynamic-form").on("click", ".remove-field", function() { $(this).closest(".form-group").remove(); updateFormState(); }); // 性能对比示例 console.time("直接绑定"); for (var i = 0; i < 1000; i++) { $("
    项目" + i + "
    ") .appendTo("#container") .click(function() { // 为每个元素绑定事件 console.log("点击"); }); } console.timeEnd("直接绑定"); // 较慢 console.time("事件委托"); $("#container").empty(); for (var i = 0; i < 1000; i++) { $("
    项目" + i + "
    ").appendTo("#container"); } $("#container").on("click", ".item", function() { // 只绑定一次 console.log("点击"); }); console.timeEnd("事件委托"); // 较快
    事件委托演示:
    • 项目1
    • 项目2
    • 项目3
    列表项数量: 3 点击计数: 0
    事件日志:
    事件委托的注意事项
    • 事件委托利用事件冒泡,如果事件不冒泡(如focus、blur),需要使用focusin/focusout
    • 过度使用事件委托可能导致事件处理逻辑复杂
    • 对于简单、静态的元素,直接绑定可能更清晰
    • 事件委托的目标选择器应尽可能具体,避免性能问题
    • 使用event.stopPropagation()要谨慎,可能影响其他事件处理

    事件流

    事件流描述事件在DOM树中传播的顺序。

    事件冒泡与捕获

    DOM事件流包括三个阶段:捕获阶段、目标阶段、冒泡阶段。

    捕获阶段
    文档 → body → div
    目标阶段
    button
    冒泡阶段
    div → body → 文档
    <!-- HTML结构 -->
    <div id="grandparent">
        <div id="parent">
            <button id="child">点击我</button>
        </div>
    </div>
    // 事件流演示
    // 默认情况下,事件处理在冒泡阶段执行
    $("#child").click(function(event) {
        console.log("子元素 - 目标阶段");
    });
    
    $("#parent").click(function(event) {
        console.log("父元素 - 冒泡阶段");
    });
    
    $("#grandparent").click(function(event) {
        console.log("祖父元素 - 冒泡阶段");
    });
    
    $(document).click(function(event) {
        console.log("文档 - 冒泡阶段");
    });
    
    // 点击按钮时输出顺序:
    // 1. 子元素 - 目标阶段
    // 2. 父元素 - 冒泡阶段
    // 3. 祖父元素 - 冒泡阶段
    // 4. 文档 - 冒泡阶段
    
    // 使用捕获阶段
    // jQuery默认不支持捕获阶段,需要使用原生addEventListener
    document.getElementById("grandparent").addEventListener("click", function(event) {
        console.log("祖父元素 - 捕获阶段");
    }, true); // true表示在捕获阶段处理
    
    document.getElementById("parent").addEventListener("click", function(event) {
        console.log("父元素 - 捕获阶段");
    }, true);
    
    // 现在点击按钮时输出顺序:
    // 1. 祖父元素 - 捕获阶段
    // 2. 父元素 - 捕获阶段
    // 3. 子元素 - 目标阶段(jQuery)
    // 4. 父元素 - 冒泡阶段(jQuery)
    // 5. 祖父元素 - 冒泡阶段(jQuery)
    // 6. 文档 - 冒泡阶段(jQuery)
    
    // 阻止事件冒泡
    $("#child").click(function(event) {
        console.log("子元素点击");
        event.stopPropagation(); // 阻止事件冒泡
        // 现在只有这个处理函数会执行
    });
    
    $("#parent").click(function(event) {
        console.log("这个不会执行,因为事件冒泡被阻止了");
    });
    
    // 阻止默认行为
    $("a").click(function(event) {
        event.preventDefault(); // 阻止链接跳转
        console.log("链接被点击,但不会跳转");
    });
    
    // 同时阻止默认行为和冒泡
    $("a").click(function(event) {
        event.preventDefault();
        event.stopPropagation();
        // 或者使用 return false
        // return false; // 等同于上面两行
    });
    
    // 事件委托中的事件流
    $("#grandparent").on("click", "#child", function(event) {
        console.log("事件委托处理");
        // 事件仍然会冒泡到#grandparent
    });
    
    // 检查事件阶段
    document.getElementById("child").addEventListener("click", function(event) {
        console.log("事件阶段:", event.eventPhase);
        // 1: 捕获阶段
        // 2: 目标阶段
        // 3: 冒泡阶段
    }, true);
    
    // 事件委托和事件流的结合
    $("#container").on("click", function(event) {
        console.log("容器点击,目标:", event.target.tagName);
    
        // 根据event.target决定如何处理
        if ($(event.target).is("button")) {
            console.log("点击了按钮");
        } else if ($(event.target).is("input")) {
            console.log("点击了输入框");
        }
    });
    
    // 事件流可视化
    function logEventFlow(event) {
        var phase;
        switch(event.eventPhase) {
            case Event.CAPTURING_PHASE: phase = "捕获"; break;
            case Event.AT_TARGET: phase = "目标"; break;
            case Event.BUBBLING_PHASE: phase = "冒泡"; break;
        }
    
        console.log(event.currentTarget.id + " - " + phase + "阶段");
    }
    
    // 为所有元素添加事件监听
    $("#grandparent, #parent, #child").each(function() {
        this.addEventListener("click", logEventFlow, true); // 捕获阶段
        this.addEventListener("click", logEventFlow, false); // 冒泡阶段
    });
    事件流演示:
    文档
    body
    div#grandparent
    div#parent
    button#child
    事件流日志:

    自定义事件

    自定义事件允许创建和触发自己的事件类型。

    创建和触发自定义事件

    自定义事件可以实现组件间的松耦合通信。

    // 绑定自定义事件
    $(selector).on("customEvent", handler)

    // 触发自定义事件
    $(selector).trigger("customEvent"[, extraParameters])

    // 使用命名空间
    $(selector).on("customEvent.namespace", handler)

    // 创建带数据的事件
    var event = $.Event("customEvent", {data: value})
    基本自定义事件:
    // 创建自定义事件
    $("#element").on("myCustomEvent", function(event, param1, param2) {
        console.log("自定义事件触发", param1, param2);
    });
    
    // 触发自定义事件
    $("#element").trigger("myCustomEvent", ["参数1", "参数2"]);
    
    // 带命名空间的自定义事件
    $("#element").on("myEvent.namespace1", function() {
        console.log("命名空间1的事件");
    });
    
    $("#element").on("myEvent.namespace2", function() {
        console.log("命名空间2的事件");
    });
    
    // 触发特定命名空间的事件
    $("#element").trigger("myEvent.namespace1");
    
    // 移除特定命名空间的事件
    $("#element").off(".namespace1");
    
    // 创建自定义事件对象
    var customEvent = $.Event("customEvent", {
        pageX: 100,
        pageY: 200,
        data: {key: "value"}
    });
    
    // 触发带自定义数据的事件
    $("#element").trigger(customEvent);
    
    // 在事件处理函数中访问自定义数据
    $("#element").on("customEvent", function(event) {
        console.log("自定义数据:", event.data); // {key: "value"}
        console.log("页面坐标:", event.pageX, event.pageY); // 100, 200
    });
    自定义事件应用场景:
    // 1. 组件间通信
    // 购物车组件
    var ShoppingCart = {
        init: function() {
            this.bindEvents();
        },
    
        bindEvents: function() {
            // 监听商品添加事件
            $(document).on("productAdded", function(event, product) {
                ShoppingCart.addProduct(product);
            });
    
            // 监听商品移除事件
            $(document).on("productRemoved", function(event, productId) {
                ShoppingCart.removeProduct(productId);
            });
        },
    
        addProduct: function(product) {
            console.log("添加商品:", product);
            // 更新购物车UI
            this.updateUI();
    
            // 触发购物车更新事件
            $(document).trigger("cartUpdated", [this.getCartItems()]);
        },
    
        removeProduct: function(productId) {
            console.log("移除商品:", productId);
            // 更新购物车UI
            this.updateUI();
    
            // 触发购物车更新事件
            $(document).trigger("cartUpdated", [this.getCartItems()]);
        },
    
        updateUI: function() {
            // 更新购物车显示
        },
    
        getCartItems: function() {
            // 返回购物车商品列表
            return [];
        }
    };
    
    // 商品列表组件
    $(".add-to-cart").click(function() {
        var product = {
            id: $(this).data("id"),
            name: $(this).data("name"),
            price: $(this).data("price")
        };
    
        // 触发商品添加事件
        $(document).trigger("productAdded", [product]);
    });
    
    // 2. 状态变化通知
    var ApplicationState = {
        currentUser: null,
    
        login: function(user) {
            this.currentUser = user;
    
            // 触发登录事件
            $(document).trigger("userLoggedIn", [user]);
        },
    
        logout: function() {
            var oldUser = this.currentUser;
            this.currentUser = null;
    
            // 触发登出事件
            $(document).trigger("userLoggedOut", [oldUser]);
        }
    };
    
    // 监听登录状态变化
    $(document).on("userLoggedIn", function(event, user) {
        console.log("用户登录:", user.name);
        updateUIForLoggedInUser(user);
    });
    
    $(document).on("userLoggedOut", function(event, user) {
        console.log("用户登出:", user.name);
        updateUIForLoggedOutUser();
    });
    
    // 3. 异步操作完成通知
    function loadUserData(userId) {
        // 模拟异步加载
        setTimeout(function() {
            var userData = {
                id: userId,
                name: "张三",
                email: "zhangsan@example.com"
            };
    
            // 数据加载完成,触发事件
            $(document).trigger("userDataLoaded", [userData]);
        }, 1000);
    }
    
    // 监听数据加载完成
    $(document).on("userDataLoaded", function(event, userData) {
        console.log("用户数据加载完成:", userData);
        renderUserProfile(userData);
    });
    
    // 开始加载数据
    loadUserData(123);
    
    // 4. 表单验证事件
    $("#registration-form").on("submit", function(event) {
        event.preventDefault();
    
        var formData = $(this).serializeArray();
        var errors = validateFormData(formData);
    
        if (errors.length === 0) {
            // 表单验证通过,触发事件
            $(this).trigger("formValid", [formData]);
        } else {
            // 表单验证失败,触发事件
            $(this).trigger("formInvalid", [errors]);
        }
    });
    
    // 监听表单验证结果
    $("#registration-form")
        .on("formValid", function(event, formData) {
            console.log("表单验证通过,提交数据");
            submitForm(formData);
        })
        .on("formInvalid", function(event, errors) {
            console.log("表单验证失败:", errors);
            displayErrors(errors);
        });
    
    // 5. 自定义事件命名空间管理
    // 为不同模块使用不同命名空间
    var UserModule = {
        namespace: "userModule",
    
        init: function() {
            this.bindEvents();
        },
    
        bindEvents: function() {
            $(document).on("login." + this.namespace, this.onLogin.bind(this));
            $(document).on("logout." + this.namespace, this.onLogout.bind(this));
        },
    
        onLogin: function(event, user) {
            console.log("用户模块: 用户登录", user);
        },
    
        onLogout: function(event, user) {
            console.log("用户模块: 用户登出", user);
        },
    
        destroy: function() {
            // 清理事件
            $(document).off("." + this.namespace);
        }
    };
    
    var CartModule = {
        namespace: "cartModule",
    
        init: function() {
            this.bindEvents();
        },
    
        bindEvents: function() {
            $(document).on("productAdded." + this.namespace, this.onProductAdded.bind(this));
        },
    
        onProductAdded: function(event, product) {
            console.log("购物车模块: 商品添加", product);
        },
    
        destroy: function() {
            // 清理事件
            $(document).off("." + this.namespace);
        }
    };
    
    // 初始化模块
    UserModule.init();
    CartModule.init();
    
    // 触发事件(所有模块都会收到)
    $(document).trigger("login", [{id: 1, name: "张三"}]);
    $(document).trigger("productAdded", [{id: 101, name: "商品A"}]);
    
    // 销毁特定模块
    UserModule.destroy(); // 只移除用户模块的事件
    自定义事件演示:
    自定义事件日志:

    综合演示

    综合演示各种事件处理技术。

    事件处理综合演示

    交互式演示面板
    鼠标事件区域
    在此区域交互
    等待交互...
    交互次数: 0
    事件计数器
    点击 0
    鼠标移动 0
    按键 0
    输入 0
    动态列表(事件委托)
    • 示例项目1
    • 示例项目2
    项目数量: 2
    事件控制面板
    综合事件日志
    日志条目: 0
    事件处理总结
    • 事件绑定: 使用 on() 方法绑定事件,off() 方法移除事件
    • 事件类型: 鼠标事件、键盘事件、表单事件、窗口事件、触摸事件
    • 事件对象: 包含事件所有信息,可使用 preventDefault()stopPropagation()
    • 事件委托: 使用 $(parent).on(event, childSelector, handler) 处理动态元素
    • 事件流: 事件传播的三个阶段:捕获、目标、冒泡
    • 自定义事件: 使用 trigger() 触发自定义事件,实现组件间通信
    • 最佳实践: 使用事件委托提高性能,合理使用事件命名空间,注意内存管理