Làm cách nào để ngăn sự kiện onclick của cha mẹ bắn khi mỏ neo con được nhấp?


346

Tôi hiện đang sử dụng jQuery để tạo một div có thể nhấp và trong div này tôi cũng có các neo. Vấn đề tôi gặp phải là khi tôi nhấp vào một neo, cả hai sự kiện nhấp đều được kích hoạt (đối với div và neo). Làm cách nào để ngăn sự kiện onclick của div kích hoạt khi nhấp vào neo?

Đây là mã bị hỏng:

JavaScript

var url = $("#clickable a").attr("href");

$("#clickable").click(function() {
    window.location = url;
    return true;
})

HTML

<div id="clickable">
    <!-- Other content. -->
    <a href="http://foo.com">I don't want #clickable to handle this click event.</a>
</div>

Câu trả lời:


458

Sự kiện bong bóng đến điểm cao nhất trong DOM mà tại đó sự kiện nhấp đã được đính kèm. Vì vậy, trong ví dụ của bạn, ngay cả khi bạn không có bất kỳ yếu tố nào có thể nhấp rõ ràng khác trong div, mọi phần tử con của div sẽ đánh bóng sự kiện nhấp chuột của chúng lên DOM cho đến khi trình xử lý sự kiện nhấp chuột của DIV bắt được nó.

Có hai giải pháp cho vấn đề này là kiểm tra xem ai thực sự bắt nguồn sự kiện. jQuery vượt qua một đối tượng eventargs cùng với sự kiện:

$("#clickable").click(function(e) {
    var senderElement = e.target;
    // Check if sender is the <div> element e.g.
    // if($(e.target).is("div")) {
    window.location = url;
    return true;
});

Bạn cũng có thể đính kèm một trình xử lý sự kiện nhấp vào các liên kết của mình để thông báo cho họ dừng sự kiện sủi bọt sau khi trình xử lý của chính họ thực thi:

$("#clickable a").click(function(e) {
   // Do something
   e.stopPropagation();
});

3
Câu trả lời chính xác. Rất vui được biết có những lựa chọn quá.
Jonathon Watney

4
+1! Đính kèm một trình xử lý nhấp chuột với stopPropagation là một mẹo rất hay, cảm ơn!
Thomas

2
nếu bạn có một loạt các yếu tố bạn muốn ngăn chặn sự lan truyền trên, bạn có thể tìm thấy yếu tố cha mẹ của chúng và đầu cũng ngăn chặn nó nổi lên ở đó. Vì vậy, thay vì chặn tất cả các liên kết trong div, hãy nói ví dụ-- chỉ cần chặn nhấp chuột ngay cả trên chính div và ngăn không cho nó tăng cao hơn nữa và bạn đã thiết lập.
sucit Xoay

21
Sử dụng if( e.target !== this) return;trong cha mẹ tốt hơn e.stopPropagation()ở trẻ em vì bạn không bao giờ biết nếu có người khác gắn một số trình xử lý với trẻ em, hoặc nếu một thư viện phải đính kèm một trình xử lý cho một đứa trẻ (và bạn không muốn gây rối với mã thư viện). Đó là một sự phân tách tốt hơn của mối quan tâm.
UTF_or_Death

3
Đặt if( e.target !== this) return;séc vào phụ huynh có nghĩa là nếu bất kỳ đứa trẻ nào khác của cha mẹ đó không có trình xử lý onClick của riêng họ được nhấp, thì không có gì xảy ra. Vì vậy, nó vô dụng đối với một tình huống mà bạn có ví dụ như div cha có thể nhấp. e.stopPropagation()hoạt động tốt tuy nhiên.
derf26

100

Sử dụng phương pháp stopPropagation , xem một ví dụ:

$("#clickable a").click(function(e) {
   e.stopPropagation();
});

Như đã nói bởi jQuery Docs:

stopPropagation phương pháp ngăn sự kiện nổi lên trên cây DOM, ngăn bất kỳ trình xử lý cha mẹ nào được thông báo về sự kiện.

Hãy nhớ rằng nó không ngăn người nghe xử lý sự kiện này (ví dụ: nhiều hơn một trình xử lý nhấp chuột cho một nút), nếu đó không phải là hiệu ứng mong muốn, bạn phải sử dụng stopImmediatePropagationthay thế.


48

Đây là giải pháp của tôi cho mọi người ngoài kia đang tìm kiếm một mã không phải jQuery (javascript thuần túy)

document.getElementById("clickable").addEventListener("click", function( e ){
    e = window.event || e; 
    if(this === e.target) {
        // put your code here
    }
});

Mã của bạn sẽ không được thực thi nếu nhấp vào con của cha mẹ


1
Điều này làm việc cho tôi, tôi cần một giải pháp không phải là JS / jQuery. 10 lần!
LA

Câu trả lời chính xác. Tôi chỉ cần thông qua sự kiện trực tiếp. Vì vậy, tôi đã không sử dụng window.event, điều mà MDN không khuyến khích: developer.mozilla.org/en-US/docs/Web/API/Window/event . Nếu bạn có thể dành thời gian tôi sẽ đánh giá cao nếu bạn có thể nhận xét lý do tại sao bạn sử dụng window.event(có thể đó là một vấn đề tồn tại trong năm 2015 hoặc tôi không hiểu lý do).
RMo

15

bạn cũng có thể thử cái này

$("#clickable").click(function(event) {
   var senderElementName = event.target.tagName.toLowerCase();
   if(senderElementName === 'div')
   {
       // do something here 
   } 
   else
   {
      //do something with <a> tag
   }
});

14

Nếu bạn không có ý định tương tác với các phần tử bên trong trong mọi trường hợp, thì một giải pháp CSS có thể hữu ích cho bạn.

Chỉ cần đặt phần tử bên trong / s thành pointer-events: none

trong trường hợp của bạn:

.clickable > a {
    pointer-events: none;
}

hoặc để nhắm mục tiêu tất cả các yếu tố bên trong nói chung:

.clickable * {
    pointer-events: none;
}

Cách hack dễ dàng này đã giúp tôi tiết kiệm rất nhiều thời gian trong khi phát triển với ReactJS

Có thể tìm thấy hỗ trợ trình duyệt tại đây: http://caniuse.com/#feat=pulum-events


8

Nếu bạn có nhiều yếu tố trong div có thể nhấp, bạn nên làm điều này:

$('#clickable *').click(function(e){ e.stopPropagation(); });

8

Sử dụng return false;hoặc e.stopPropogation();sẽ không cho phép thêm mã để thực thi. Nó sẽ dừng dòng chảy tại điểm này.


Vâng, điều này rất quan trọng - bản thân tôi đã chạy vào đây. Nhưng câu trả lời ở trên từ Rex rất hữu ích - có thể lấy phần tử được nhấp và trong một số trường hợp sử dụng điều này trong logic mà bạn đang cố gắng dừng lại. .target.nodeName cũng hữu ích để có được một ý tưởng rõ ràng về những gì đã được nhấn.
Watercayman


4

Thay thế nội tuyến:

<div>
    <!-- Other content. -->
    <a onclick='event.stopPropagation();' href="http://foo.com">I don't want #clickable to handle this click event.</a>
</div>

3

Đây là một ví dụ sử dụng Angular 2+

Ví dụ: nếu bạn muốn đóng Thành phần Modal nếu người dùng nhấp bên ngoài nó:

// Close the modal if the document is clicked.

@HostListener('document:click', ['$event'])
public onDocumentClick(event: MouseEvent): void {
  this.closeModal();
}

// Don't close the modal if the modal itself is clicked.

@HostListener('click', ['$event'])
public onClick(event: MouseEvent): void {
  event.stopPropagation();
}

1

Bạn cần ngăn sự kiện tiếp cận (sủi bọt đến) cha mẹ (div). Xem phần về bong bóng ở đây và thông tin API dành riêng cho jQuery tại đây .


Mát mẻ. Cảm ơn thông tin về sự kiện sủi bọt.
Jonathon Watney

1

var inner = document.querySelector("#inner");
var outer = document.querySelector("#outer");
inner.addEventListener('click',innerFunction);
outer.addEventListener('click',outerFunction);

function innerFunction(event){
  event.stopPropagation();
  console.log("Inner Functiuon");
}

function outerFunction(event){
  console.log("Outer Functiuon");
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Pramod Kharade-Event with Outer and Inner Progration</title>
</head>
<body>
<div id="outer" style="width:100px;height:100px;background-color:green;">
  <div id="inner" style="width:35px;height:35px;background-color:yellow;"></div>
</div>
</body>
</html>


0

Để chỉ định một số phần tử phụ là không thể ghi được, hãy viết cấu trúc phân cấp css như trong ví dụ dưới đây.

Trong ví dụ này, tôi dừng truyền bá cho bất kỳ phần tử nào (*) bên trong td bên trong tr bên trong một bảng có lớp ".subtable"

$(document).ready(function()
{    
   $(".subtable tr td *").click(function (event)
   {
       event.stopPropagation();
   });

});

0

ignParent () là một giải pháp JavaScript thuần túy.

Nó hoạt động như một lớp trung gian so sánh tọa độ của nhấp chuột với tọa độ của phần tử con / s. Hai bước thực hiện đơn giản:

1. Đặt mã ignParent () trên trang của bạn.

2. Thay vì onclick gốc của cha mẹ = "ParentEvent ();" , viết:

onclick="ignoreParent(['parentEvent()', 'child-ID']);"

Bạn có thể chuyển ID của bất kỳ số phần tử con nào cho hàm và loại trừ các phần tử khác.

Nếu bạn nhấp vào một trong các phần tử con, sự kiện cha sẽ không kích hoạt. Nếu bạn đã bấm vào cha mẹ, nhưng không phải vào bất kỳ phần tử con nào [được cung cấp dưới dạng đối số], thì sự kiện cha sẽ bị hủy.

mã ignParent () trên Github


0

Nếu nó nằm trong ngữ cảnh nội tuyến, trong HTML hãy thử điều này:

onclick="functionCall();event.stopPropagation();

-1

Trong trường hợp ai đó gặp vấn đề này khi sử dụng React, đây là cách tôi giải quyết nó.

scss:

#loginBackdrop {
position: absolute;
width: 100% !important;
height: 100% !important;
top:0px;
left:0px;
z-index: 9; }

#loginFrame {
width: $iFrameWidth;
height: $iFrameHeight;
background-color: $mainColor;
position: fixed;
z-index: 10;
top: 50%;
left: 50%;
margin-top: calc(-1 * #{$iFrameHeight} / 2);
margin-left: calc(-1 * #{$iFrameWidth} / 2);
border: solid 1px grey;
border-radius: 20px;
box-shadow: 0px 0px 90px #545454; }

Kết xuất của thành phần ():

render() {
    ...
    return (
        <div id='loginBackdrop' onClick={this.props.closeLogin}>
            <div id='loginFrame' onClick={(e)=>{e.preventDefault();e.stopPropagation()}}>
             ... [modal content] ...
            </div>
        </div>
    )
}

Bằng cách thêm chức năng onClick cho các sự kiện nhấp chuột (mod nội dung) con chuột được ngăn chặn để đạt đến chức năng 'closeLogin' của phần tử cha.

Điều này đã tạo ra mánh khóe cho tôi và tôi đã có thể tạo hiệu ứng phương thức với 2 div đơn giản.


-3

thêm anhư sau:

<a href="http://foo.com" onclick="return false;">....</a>

hoặc return false;từ trình xử lý nhấp chuột cho #clickablethích:

  $("#clickable").click(function() {
        var url = $("#clickable a").attr("href");
        window.location = url;
        return false;
   });

-3

Tất cả các giải pháp là phức tạp và của jscript. Đây là phiên bản đơn giản nhất:

var IsChildWindow=false;

function ParentClick()
{
    if(IsChildWindow==true)
    {
        IsChildWindow==false;
        return;
    }
    //do ur work here   
}


function ChildClick()
{
    IsChildWindow=true;
    //Do ur work here    
}

3
tôi nghĩ bạn đã mắc lỗi trong dòng "IsChildWindow == false;" - không nên là "IsChildWindow = false;"?
Andre Schweighofer

-5
<a onclick="return false;" href="http://foo.com">I want to ignore my parent's onclick event.</a>

5
Điều này cũng ngăn chặn các liên kết điều hướng.
Rex M

Có, hoặc không những gì cần thiết?. Hoặc cần phải được nevegar?
andres descalzo
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.