You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用jQuery实现先触发ul hover事件再触发li hover事件

根本原因

出现该触发顺序是浏览器的默认行为:jQuery的hover()方法绑定的是mouseenter和mouseleave事件,这两个事件不会冒泡,触发时机是指针进入元素自身区域时。当从外部移入嵌套在ul内部的li时,指针会先命中层级更具体的li元素,因此li的mouseenter先触发,之后才会触发父元素ul的mouseenter。

解决方案1:微任务延迟li触发逻辑(改动最小)

只需要给li的hover移入回调包裹一层微任务,让它等当前同步任务(包含ul的hover回调)全部执行完再运行,即可满足顺序要求,原有逻辑几乎不用改:

function bindHoverEvents() {
    $('#list').hover(
        () => console.log("1. List hover"),
        () => console.log("4. List unhover")
    );
    $('.list-item').hover(
        // 用微任务推迟执行,确保ul的hover先跑完
        () => Promise.resolve().then(() => console.log("2. Item hover")),
        () => console.log("3. Item unhover.")
    );
}

解决方案2:捕获阶段绑定父元素事件(更稳定)

如果业务逻辑比较复杂,担心微任务时序不可控,可以改用支持事件流的mouseover/mouseout事件,把父元素ul的事件绑定在捕获阶段,天然保证父元素事件先于子元素触发:

function bindHoverEvents() {
    const list = document.querySelector('#list');
    // 第三个参数传true代表绑定到捕获阶段,父元素先触发
    list.addEventListener('mouseover', (e) => {
        // 只在进入ul本身时触发,避免子元素冒泡的重复触发
        if (e.target === list) {
            console.log("1. List hover");
        }
    }, true);
    list.addEventListener('mouseout', (e) => {
        if (e.target === list) {
            console.log("4. List unhover");
        }
    }, true);

    // li的hover事件无需特殊调整
    $('.list-item').hover(
        () => console.log("2. Item hover"),
        () => console.log("3. Item unhover.")
    );
}

两种方案运行后,移入再移出li的控制台输出都符合期望的顺序。


内容的提问来源于stack exchange,提问作者tomashauser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 18:27:02