Как остановить распространение событий с помощью встроенного атрибута onclick?


313

Учтите следующее:

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

Как я могу сделать так, чтобы, когда пользователь нажимает промежуток, он не запускает div запускал событие click?

Ответы:


272

Используйте event.stopPropagation () .

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

Для IE: window.event.cancelBubble = true

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

11
В FireFox нет такого объекта как событие.
Роберт С. Барт

6
Объект события является параметром обратного вызова. На самом деле в IE не существует такого объекта, как объект события, потому что этот объект доступен через window.event, а не является параметром функции :-)
Винсент Роберт,

66
Это просто неправильно - встроенные обработчики onclick не передают событие в качестве аргумента. Правильное решение - Гаретс, ниже.
Benubird

2
В Firefox вы можете получить доступ к переменному событию во встроенном скрипте, но window.event недоступен. <div onclick = "alert (event);"> </ div>
Морган Чен

1
eventПохоже, что он доступен и для встроенных событий в IOS Safari.
Юваль А.

210

Есть два способа получить объект события внутри функции:

  1. Первый аргумент в W3C-совместимом браузере (Chrome, Firefox, Safari, IE9 +)
  2. Объект window.event в Internet Explorer (<= 8)

Если вам нужно поддерживать устаревшие браузеры, которые не следуют рекомендациям W3C, обычно внутри функции вы используете что-то вроде следующего:

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

который проверит сначала один, а затем другой и сохранит то, что было найдено внутри переменной события. Однако в встроенном обработчике событий нет eобъекта для использования. В этом случае вам нужно воспользоваться argumentsколлекцией, которая всегда доступна и ссылается на полный набор аргументов, передаваемых функции:

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

Однако, вообще говоря, вы должны избегать встроенных обработчиков событий, если вам нужно что-то сложное, например, остановить распространение. Написание ваших обработчиков событий отдельно и присоединение их к элементам - гораздо лучшая идея в среднесрочной и долгосрочной перспективе, как для удобочитаемости, так и для удобства обслуживания.


11
Из встроенного слушателя вы можете передать объект события как:, onclick="foo(event)"затем в функцию function foo(event){/* do stuff with event */}. Это работает в моделях событий IE и W3C.
RobG

5
Это «меньше или равно восьми» несколько ... неоднозначно.
TechNyquist

8
это на самом деле не отвечает на вопрос.
jcomeau_ictx

1
аккуратный ответ на другой вопрос. : - /
Арель

80

Имейте в виду, что window.event не поддерживается в FireFox, и поэтому оно должно быть примерно таким:

e.cancelBubble = true

Или вы можете использовать стандарт W3C для FireFox:

e.stopPropagation();

Если вы хотите стать модным, вы можете сделать это:

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

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

12
И чтобы это работало, нужно назвать это так:<div onclick="myEventHandler(event);">
DarkDust

1
Это может быть «событие || window.event».
Заостренный

1
если (e.cancelBubble) мне не подходит, вы устанавливаете его в true, если это уже правда
Guillaume86

e.cancelBubbleвозвращает ложь в IE! Это не может достичь e.cancelBubble = true;инструкции. Вместо этого используйте условие SoftwareARM !!
Мауретто

45

Используйте эту функцию, она проверит наличие правильного метода.

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

20

У меня была та же самая проблема - окно ошибки js в IE - это прекрасно работает во всех браузерах, насколько я вижу (event.cancelBubble = true делает работу в IE)

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

1
Спасибо @MSC именно то, что мне нужно!
DannyC

1
Встроенный скрипт. Это действительно отвечает на вопрос
Цезарь

10

Это сработало для меня

<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>

Вы уверены, что этот фрагмент кода сработал для вас? Потому что похоже, что есть проблема с цитированием строк в обработчике onclick внешнего div ...?!
Николь

7

Для веб-страниц ASP.NET (не MVC) вы можете использовать Sys.UI.DomEventобъект как оболочку нативного события.

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

или передать событие в качестве параметра внутренней функции:

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

и в некоторых функциях:

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


2

Я не могу комментировать из-за кармы, поэтому я пишу это как полный ответ: в соответствии с ответом Гарета (var e = arguments [0] || window.event; [...]) я использовал этот oneliner, встроенный в onclick для быстрый взлом:

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

Я знаю, что уже поздно, но я хотел, чтобы вы знали, что это работает в одну строку. Фигурные скобки возвращают событие, к которому в обоих случаях присоединена функция stopPropagation, поэтому я попытался заключить их в фигурные скобки, как в случаях if и ...., это работает. :)


1

Это также работает - в ссылке HTML используйте onclick с return следующим образом:

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

И тогда функция comfirmClick () должна выглядеть так:

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

2
Это не то, что имел в виду вопрос.
jzonthemtn

@jbird Это именно то, что имел в виду вопрос. Это другой (более старый) способ отменить событие, чем всплывающее дерево dom (это в спецификациях dom api level 1).
gion_13

@ gion_13 Но действие клика - это не то, что пользователь должен подтвердить. В этом вопросе мы хотим, чтобы onclick () ребенка запускался, а не onclick () родителя. Помещать подсказки между ними не полезно. Я надеюсь, что вы можете увидеть эту разницу.
jzonthemtn

1
Это confirmне актуально. Я имею в виду возвращаемое значение . цитата: В ссылке HTML используйте onclick с return, как это
gion_13

возвращая ложные отмены по ссылке, это не отменяет распространение на моем chrome
commonpike

1

Почему бы просто не проверить, какой элемент был нажат? Если вы щелкаете по чему-либо, window.event.targetон присваивается элементу, по которому был выполнен щелчок, и этот элемент также может быть передан в качестве аргумента.

Если цель и элемент не равны, это было событие, которое распространялось вверх.

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

Спасибо, приятель, это, кажется, самое чистое решение здесь. Что касается сопутствующего примечания, вы должны учесть, что это совпадает только тогда, когда нажатый элемент является фактическим верхним элементом.
Саймон Маттес

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

Лучшее решение - обработать событие с помощью функции javascript, но для того, чтобы использовать простое и быстрое решение, использующее непосредственно элемент html, и как только «event» и «window.event» устарели и не будут поддерживаться повсеместно ( https://developer.mozilla.org/en-US/docs/Web/API/Window/event ), я предлагаю следующий «жесткий код»:

<div onclick="alert('blablabla'); (arguments[0] ? arguments[0].stopPropagation() : false);">...</div>
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.