Làm cách nào để tắt các sự kiện di chuột ra do các phần tử con kích hoạt?


107

Hãy để tôi mô tả vấn đề chi tiết:

Tôi muốn hiển thị một div được định vị tuyệt đối khi di chuột qua một phần tử. Điều đó thực sự đơn giản với jQuery và hoạt động tốt. Nhưng khi chuột đi qua một trong các phần tử con, nó sẽ kích hoạt sự kiện di chuột của div chứa. Làm cách nào để ngăn javascript kích hoạt sự kiện mouseout của phần tử chứa khi di chuột qua phần tử con.

Cách tốt nhất và ngắn nhất để làm điều đó với jQuery là gì?

Đây là một ví dụ đơn giản để minh họa ý tôi:

Html:

<a>Hover Me</a>
<div>
  <input>Test</input>
  <select>
    <option>Option 1</option>
    <option>Option 2</option>
  </select>
</div>

Javascript / jQuery:

$('a').hover( function() { $(this).next().show() }
              function() { $(this).next().hide() } );

Câu trả lời:


209

Câu hỏi hơi cũ, nhưng tôi đã gặp phải vấn đề này vào ngày hôm trước.

Cách đơn giản nhất để thực hiện việc này với các phiên bản jQuery gần đây là sử dụng mouseentermouseleavecác sự kiện thay vì mouseovermouseout.

Bạn có thể nhanh chóng kiểm tra hành vi với:

$(".myClass").on( {
   'mouseenter':function() { console.log("enter"); },
   'mouseleave':function() { console.log("leave"); }
});

4
Đã giúp vấn đề liên quan đến javascript không phải jquery của tôi. Tôi đã sử dụng mouseenter / mouseout thay vì mouseleave với trình nghe sự kiện của mình!
Jo E.

1
Vì lợi ích tìm kiếm, các hành vi sự kiện chuột này tương đương với ROLL_OVERROLL_OUTtrong AS3.
Jeff Ward

2
Giúp tôi đỡ đau đầu. mouseoutThật kỳ lạ khi việc di chuột trên các phần tử con sẽ kích hoạt sự kiện của cha mẹ , trong khi thực tế, sự kiện của nó vẫn ở bên trong phần tử mẹ.
javiniar.leonard

18

Vì mục đích đơn giản, tôi chỉ tổ chức lại html một chút để đưa nội dung mới được hiển thị vào bên trong phần tử mà sự kiện di chuột liên kết với:

<div id="hoverable">
  <a>Hover Me</a>
  <div style="display:none;">
    <input>Test</input>
    <select>
      <option>Option 1</option>
      <option>Option 2</option>
    </select>
  </div>
</div>

Sau đó, bạn có thể làm điều gì đó như sau:

$('#hoverable').hover( function() { $(this).find("div").show(); },
                       function() { $(this).find("div").hide(); } );

Lưu ý: Tôi không đề xuất css nội tuyến, nhưng nó đã được thực hiện để làm cho ví dụ dễ hiểu hơn.


Đây quả thực là một giải pháp rất đơn giản và sạch sẽ. Cảm ơn vì đã nhắc tôi. Nhưng trong tình huống cụ thể của tôi, không chính xác như trong câu hỏi, đây không phải là một lựa chọn. Cảm ơn mặc dù!
Sander Versluys

Sau khi thử các phương pháp khác nhau như được mô tả bởi những người khác ở đây tại SO, tôi đã quay lại phương pháp của bạn và làm cho nó hoạt động trong trường hợp của tôi. Yay! :-)
Sander Versluys 09/08/08

11

Yeap, các bạn, hãy sử dụng .mouseleavethay vì .mouseout:

$('div.sort-selector').mouseleave(function() {
    $(this).hide();
});

Hoặc thậm chí sử dụng nó kết hợp với live:

$('div.sort-selector').live('mouseleave', function() {
    $(this).hide();
});

8

Bạn đang tìm kiếm jQuery tương đương với javascript ngăn sự kiện sôi nổi.

Kiểm tra cái này:

http://docs.jquery.com/Events/jQuery.Event#event.stopPropagation.28.29

Về cơ bản, bạn cần phải nắm bắt sự kiện trong các nút DOM con, và ở đó dừng sự truyền bá của chúng lên cây DOM. Một cách khác, mặc dù thực sự không được đề xuất (vì nó có thể gây xáo trộn nghiêm trọng với các sự kiện hiện có trên trang của bạn), là đặt tính năng chụp sự kiện thành một phần tử cụ thể trên trang và nó sẽ nhận tất cả các sự kiện. Điều này hữu ích cho hành vi DnD và như vậy, nhưng chắc chắn không phải cho trường hợp của bạn.


điều này hoạt động như bình thường, không biết tại sao bạn không thể làm cho nó hoạt động .. chỉ là một thông tin, một liên kết đến tài liệu đã thay đổi, liên kết mới là docs.jquery.com/Events/jQuery.Event#event.stopPropagation. 28,29
zappan

3

Tôi chỉ đơn giản là kiểm tra xem tọa độ chuột có nằm ngoài phần tử trong sự kiện mouseout hay không.

Nó hoạt động nhưng đó là rất nhiều mã cho một thứ đơn giản như vậy :(

function mouseOut(e)
{
    var pos = GetMousePositionInElement(e, element);
    if (pos.x < 0 || pos.x >= element.size.X || pos.y < 0 || pos.y >= element.size.Y)
    {
        RealMouseOut();
    }
    else
    {
         //Hit a child-element
    }
}

Mã bị cắt giảm để dễ đọc, sẽ không hoạt động ngoài hộp.


1

Tôi đồng ý với Ryan.

Vấn đề của bạn là div "tiếp theo" không phải là "con" của A. Không có cách nào để HTML hoặc jQuery biết rằng phần tử "a" của bạn có liên quan đến div con trong DOM. Gói chúng và đặt một con chuột lên trên wrapper có nghĩa là chúng được liên kết với nhau.

Tuy nhiên, xin lưu ý rằng mã của anh ấy không phù hợp với các phương pháp hay nhất. Không đặt nội tuyến kiểu ẩn trên các phần tử; nếu người dùng có CSS ​​nhưng không phải javascript, phần tử sẽ ẩn và không thể hiển thị. Thực hành tốt hơn là đặt khai báo đó trong sự kiện document.ready.


Tôi hoàn toàn đồng ý với việc đặt ẩn trong sự kiện document.ready. Css nội tuyến chỉ để truyền đạt một ví dụ làm việc đầy đủ theo cách đơn giản nhất có thể. Tôi sẽ chỉnh sửa câu trả lời của mình để làm rõ điều đó.
Ryan McGeary 09/08/08

1

Tôi đã giải quyết vấn đề này bằng cách thêm pointer-events: none;vào các phần tử con của tôi css


Điều này thực sự đã giúp ích rất nhiều khi sửa một số mã kế thừa xây dựng các cửa sổ bật lên của riêng nó với các sự kiện di chuột qua và di chuyển
CM

0

Cách tôi thường thấy điều này được xử lý là có độ trễ khoảng 1/2 giây giữa việc di chuyển chuột từ phần tử HoverMe. Khi di chuyển chuột vào phần tử được di chuột, bạn sẽ muốn đặt một số biến báo hiệu rằng bạn đang di chuột qua phần tử, và sau đó về cơ bản ngăn phần được di chuột qua ẩn nếu biến này được đặt. Sau đó, bạn phải thêm một chức năng ẩn tương tự OnMouseOut từ phần tử được di chuột để làm cho nó biến mất khi bạn loại bỏ chuột. Xin lỗi, tôi không thể cung cấp cho bạn bất kỳ mã nào hoặc một cái gì đó cụ thể hơn, nhưng tôi hy vọng điều này sẽ giúp bạn đi đúng hướng.


Có idd Tôi vừa thực hiện một giải pháp như vậy. Đó là một vấn đề thực sự phổ biến. Tôi thực sự tò mò những giải pháp khác có ... Cảm ơn câu trả lời!
Sander Versluys

0

Đó là một câu hỏi cũ, nhưng nó không bao giờ trở nên lỗi thời. Câu trả lời đúng phải là câu trả lời bởi bytebrite .

Tôi chỉ muốn chỉ ra sự khác biệt giữa mouseover / mouseout và mouseenter / mouseleave. Bạn có thể đọc một lời giải thích hữu ích và tuyệt vời ở đây (đi đến cuối trang để xem bản demo đang hoạt động). Khi bạn sử dụng mouseout, sự kiện sẽ dừng lại khi chuột vào phần tử khác, ngay cả khi đó là phần tử con. Mặt khác, khi bạn sử dụng mouseleave, sự kiện không được kích hoạt khi chuột qua phần tử con và đây là hành vi mà OP muốn đạt được.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.