Làm thế nào để ngăn chặn sự lan truyền sự kiện với thuộc tính onclick nội tuyến?


313

Hãy xem xét những điều sau đây:

<div onclick="alert('you clicked the header')" class="header">
  <span onclick="alert('you clicked inside the header');">something inside the header</span>
</div>

Làm cách nào tôi có thể làm cho nó để khi người dùng nhấp vào nhịp, nó không divkích hoạt sự kiện nhấp chuột?

Câu trả lời:


272

Sử dụng event.stopPropagation () .

<span onclick="event.stopPropagation(); alert('you clicked inside the header');">something inside the header</span>

Dành cho IE: window.event.cancelBubble = true

<span onclick="window.event.cancelBubble = true; alert('you clicked inside the header');">something inside the header</span>

11
Không có thứ gọi là đối tượng sự kiện trong FireFox.
Robert C. Barth

6
Đối tượng sự kiện là một tham số của cuộc gọi lại. Trên thực tế, không có thứ gọi là đối tượng sự kiện trong IE vì đối tượng này có thể truy cập thông qua window.event thay vì là một tham số của hàm :-)
Vincent Robert

66
Điều này là sai - trình xử lý onclick nội tuyến không làm cho sự kiện được thông qua như một đối số. Giải pháp đúng là Gareths, dưới đây.
Benubird

2
Trong Firefox, bạn có thể có quyền truy cập vào một sự kiện thay đổi trong tập lệnh nội tuyến, nhưng window.event không khả dụng. <div onclick = "alert (sự kiện);"> </ div>
Morgan Cheng

1
eventdường như cũng có sẵn trong các sự kiện nội tuyến trong IOS Safari.
Yuval A.

210

Có hai cách để lấy đối tượng sự kiện từ bên trong một hàm:

  1. Đối số đầu tiên, trong trình duyệt tuân thủ W3C (Chrome, Firefox, Safari, IE9 +)
  2. Đối tượng window.event trong Internet Explorer (<= 8)

Nếu bạn cần hỗ trợ các trình duyệt cũ không tuân theo các khuyến nghị của W3C, thông thường bên trong một chức năng bạn sẽ sử dụng một cái gì đó như sau:

function(e) {
  var event = e || window.event;
  [...];
}

cái nào sẽ kiểm tra cái đầu tiên, rồi cái kia và lưu trữ cái nào được tìm thấy bên trong biến sự kiện. Tuy nhiên, trong một trình xử lý sự kiện nội tuyến không có eđối tượng để sử dụng. Trong trường hợp đó, bạn phải tận dụng argumentsbộ sưu tập luôn có sẵn và tham chiếu đến bộ đối số hoàn chỉnh được truyền cho một hàm:

onclick="var event = arguments[0] || window.event; [...]"

Tuy nhiên, nói chung, bạn nên tránh các trình xử lý sự kiện nội tuyến nếu bạn cần bất kỳ điều gì phức tạp như dừng truyền bá. Viết các trình xử lý sự kiện của bạn một cách riêng biệt và gắn chúng vào các yếu tố là một ý tưởng tốt hơn nhiều trong trung và dài hạn, cả về khả năng đọc và bảo trì.


11
Từ một trình nghe nội tuyến, bạn có thể truyền đối tượng sự kiện như : onclick="foo(event)", sau đó trong hàm function foo(event){/* do stuff with event */}. Điều này hoạt động trong cả hai mô hình sự kiện IE và W3C.
RobG

5
Rằng "ít hơn hoặc bằng tám" có phần ... mơ hồ.
TechNyquist

8
Điều này không thực sự trả lời câu hỏi.
jcomeau_ictx

1
câu trả lời gọn gàng cho một câu hỏi khác nhau. : - /
Arel

80

Hãy nhớ rằng window.event không được hỗ trợ trong FireFox và do đó, nó phải là một cái gì đó dọc theo dòng:

e.cancelBubble = true

Hoặc, bạn có thể sử dụng tiêu chuẩn W3C cho FireFox:

e.stopPropagation();

Nếu bạn muốn nhận được ưa thích, bạn có thể làm điều này:

function myEventHandler(e)
{
    if (!e)
      e = window.event;

    //IE9 & Other Browsers
    if (e.stopPropagation) {
      e.stopPropagation();
    }
    //IE8 and Lower
    else {
      e.cancelBubble = true;
    }
}

12
Và để làm cho nó hoạt động, người ta cần gọi như thế này:<div onclick="myEventHandler(event);">
DarkDust

1
Nó có thể là "sự kiện | | window.event".
Pointy

1
nếu (e.celonBubble) không phù hợp với tôi, bạn đặt nó thành đúng nếu nó đã đúng
Guillaume86

e.cancelBubbletrả về false trong IE! Nó không thể đạt được e.cancelBubble = true;hướng dẫn. Sử dụng điều kiện của SoftwareARM thay thế !!
mauretto

45

Sử dụng chức năng này, nó sẽ kiểm tra sự tồn tại của phương thức chính xác.

function disabledEventPropagation(event)
{
   if (event.stopPropagation){
       event.stopPropagation();
   }
   else if(window.event){
      window.event.cancelBubble=true;
   }
}

20

Tôi gặp vấn đề tương tự - hộp lỗi js trong IE - điều này hoạt động tốt trong tất cả các trình duyệt theo như tôi có thể thấy (event.catteryBubble = true thực hiện công việc trong IE)

onClick="if(event.stopPropagation){event.stopPropagation();}event.cancelBubble=true;"

1
Cảm ơn @MSC chính xác những gì tôi cần!
DanielC

1
Kịch bản nội tuyến. Nó trả lời câu hỏi
Cesar

10

Điều này làm việc cho tôi

<script>
function cancelBubble(e) {
 var evt = e ? e:window.event;
 if (evt.stopPropagation)    evt.stopPropagation();
 if (evt.cancelBubble!=null) evt.cancelBubble = true;
}
</script>

<div onclick="alert('Click!')">
  <div onclick="cancelBubble(event)">Something inside the other div</div>
</div>

Bạn có chắc chắn rằng đoạn mã chính xác này đã làm việc cho bạn? Bởi vì có vẻ như có một vấn đề trích dẫn chuỗi trong trình xử lý onclick của div bên ngoài ...?!
Nicole

7

Đối với các trang web ASP.NET (không phải MVC), bạn có thể sử dụng Sys.UI.DomEventđối tượng làm trình bao bọc của sự kiện gốc.

<div onclick="event.stopPropagation();" ...

hoặc, truyền sự kiện dưới dạng tham số cho hàm bên trong:

<div onclick="someFunction(event);" ...

và trong một số chức năng:

function someFunction(event){
    event.stopPropagation(); // here Sys.UI.DomEvent.stopPropagation() method is used
    // other onclick logic
}


2

Tôi không thể nhận xét vì Karma vì vậy tôi viết toàn bộ câu trả lời này: Theo câu trả lời của Gareth (var e = argument [0] | | window.event; [...]) Tôi đã sử dụng nội tuyến oneliner này trên onclick cho a hack nhanh:

<div onclick="(arguments[0] || window.event).stopPropagation();">..</div>

Tôi biết là muộn nhưng tôi muốn cho bạn biết rằng điều này hoạt động trong một dòng. Các dấu ngoặc nhọn trả về một sự kiện có chức năng stopPropagation được gắn trong cả hai trường hợp, vì vậy tôi đã cố gắng gói chúng trong các dấu ngoặc như trong if và .... nó hoạt động. :)


1

Điều này cũng hoạt động - Trong liên kết HTML, sử dụng onclick với return như thế này:

<a href="mypage.html" onclick="return confirmClick();">Delete</a>

Và sau đó, hàm comfirmClick () sẽ giống như:

function confirmClick() {
    if(confirm("Do you really want to delete this task?")) {
        return true;
    } else {
        return false;
    }
};

2
Đây không phải là những gì câu hỏi có nghĩa.
jzonthemtn

@jbird Đó chính xác là những gì câu hỏi có nghĩa. Đó là một cách khác (cũ hơn) để hủy bỏ một sự kiện từ việc sủi bọt lên cây dom (đó là trong thông số kỹ thuật cấp 1 của api).
gion_13

@ gion_13 Nhưng hành động của nhấp chuột không phải là thứ mà người dùng cần xác nhận. Trong câu hỏi, chúng tôi chỉ muốn đứa trẻ onclick () kích hoạt chứ không phải onclick của cha mẹ (). Đặt một dấu nhắc người dùng ở giữa những điều đó là không hữu ích. Tôi hy vọng bạn có thể thấy sự khác biệt này.
jzonthemtn

1
Các confirmlà không có liên quan. Tôi đang đề cập đến giá trị trả lại . trích dẫn: Trong liên kết HTML, sử dụng onclick với return như thế này
gion_13

trả lại sai hủy theo liên kết, nó không hủy bỏ sự lan truyền trên chrome của tôi
thường

1

Tại sao không kiểm tra phần tử nào được nhấp? Nếu bạn nhấp vào một cái gì đó, window.event.targetđược gán cho phần tử được nhấp phần tử được nhấp cũng có thể được chuyển qua làm đối số.

Nếu mục tiêu và phần tử không bằng nhau, thì đó là một sự kiện lan truyền.

function myfunc(el){
  if (window.event.target === el){
      // perform action
  }
}
<div onclick="myfunc(this)" />

Cảm ơn bạn, đây dường như là giải pháp sạch nhất ở đây. Trên một lưu ý phụ bạn phải xem xét, mặc dù điều này chỉ phù hợp khi phần tử được nhấp là phần tử trên cùng thực tế.
Simon Mattes

0
<div onclick="alert('you clicked the header')" class="header">
  <span onclick="alert('you clicked inside the header'); event.stopPropagation()">
    something inside the header
  </span>
</div>

0

Giải pháp tốt nhất sẽ được xử lý với sự kiện thông qua chức năng javascript, nhưng để sử dụng giải pháp đơn giản và nhanh chóng bằng cách sử dụng phần tử html trực tiếp và một khi "sự kiện" và "window.event" không được hỗ trợ và không được hỗ trợ phổ biến ( https://developer.mozilla.org/en-US/docs/Web/API/Window/event ), tôi đề xuất "mã cứng" sau:

<div onclick="alert('blablabla'); (arguments[0] ? arguments[0].stopPropagation() : false);">...</div>
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.