event.stopPropagation和event.preventDefault有什么区别?

Rud*_*die 761 javascript events preventdefault stoppropagation

他们似乎在做同样的事情......一个是现代的还是一个旧的?或者它们是否受不同浏览器的支持?

当我自己处理事件(没有框架)时,我总是检查两者并执行两者(如果存在).(我也是return false,但我觉得这与附加的事件无关node.addEventListener).

那两个为什么呢?我应该继续检查两者吗?或者实际上有区别吗?

(我知道,很多问题,但它们都是一样的=))

Ray*_*nos 944

stopPropagation 阻止事件冒泡事件链.

preventDefault 阻止浏览器对该事件进行的默认操作.

让我们说你有

$("#but").click(function (event) {
  event.preventDefault()
})
$("#foo").click(function () {
  alert("parent click event fired!")
})
Run Code Online (Sandbox Code Playgroud)

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <button id="but">button</button>
</div>
Run Code Online (Sandbox Code Playgroud)
$("#but").click(function (event) {
  event.stopPropagation()
})
$("#foo").click(function () {
  alert("parent click event fired!")
})
Run Code Online (Sandbox Code Playgroud)

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <button id="but">button</button>
</div>
Run Code Online (Sandbox Code Playgroud)
$("#but").click(function (event) {
  event.preventDefault()
})
$("#foo").click(function () {
  alert("parent click event fired!")
})
Run Code Online (Sandbox Code Playgroud)

随着stopPropagation只是点击按钮的处理程序被调用,div的单击处理程序永远不会触发.

就好像你只是button浏览器默认操作被停止但div的点击处理程序仍然会触发.

以下是来自div和的DOM事件对象的一些文档preventDefault

MDN:

对于IE9和FF,您可以使用preventDefault和stopPropagation.

为了支持IE8和更低的更换stopPropagationcancelBubble和替换preventDefaultreturnValue

  • 值得注意的是(如果你不看MSDN文档)`cancelBubble`和`returnValue`都是属性(所以应该设置`cancelBubble = true;`),并且`preventDefault`和`stopPropagation`是方法(因此应该称为`preventDefault();`) (7认同)
  • 按钮的默认浏览器行为是什么? (4认同)
  • @Raynos,只是一个注意事项:event.stopPropagation() 不仅阻止事件在事件链上冒泡,还在捕获阶段阻止事件传播(https://developer.mozilla.org/en-US/文档/Web/API/事件/停止传播) (3认同)
  • 知道单击按钮的默认操作是什么会很有帮助,这样我就可以解释为什么 `stopDefault()` 与 `stopPropagation()` 的工作方式不同。如果默认操作没有调用 `onclick` 方法,那是什么? (3认同)
  • @gaurav5430,根据[标准](https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element),默认行为取决于其类型和上下文:如果是在表单中键入提交按钮,则默认行为将是提交表单。 (2认同)

Ash*_*kan 227

术语

来自quirksmode.org:

事件捕获

使用事件捕获时

               | |
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  \ /          |     |
|   -------------------------     |
|        Event CAPTURING          |
-----------------------------------

element1的事件处理程序首先触发,element2的事件处理程序最后触发.

事件冒泡

当您使用事件冒泡时

               / \
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event BUBBLING           |
-----------------------------------

element2的事件处理程序首先触发,element1的事件处理程序最后触发.

首先捕获在W3C事件模型中发生的任何事件,直到它到达目标元素,然后再次冒泡.

                 | |  / \
-----------------| |--| |-----------------
| element1       | |  | |                |
|   -------------| |--| |-----------     |
|   |element2    \ /  | |          |     |
|   --------------------------------     |
|        W3C event model                 |
------------------------------------------

接口

来自w3.org,用于事件捕获:

如果捕获EventListener希望阻止事件的进一步处理发生,则它可以调用接口的stopPropagation方法 Event.这将阻止进一步调度事件,尽管EventListeners在同一层次结构级别注册的其他事件仍将接收事件.一旦stopPropagation 调用了事件的方法,对该方法的进一步调用就没有额外的效果.如果没有其他捕获器存在且stopPropagation尚未被调用,则该事件会EventListeners在目标本身上触发相应的捕获 .

对于事件冒泡:

任何事件处理程序都可以通过调用接口的stopPropagation方法来选择阻止进一步的事件传播Event.如果任何 EventListener调用此方法,将触发EventListeners当前所有额外的操作,EventTarget但冒泡将停止在该级别.只需要一次通话就stopPropagation可以防止进一步冒泡.

对于活动取消:

取消通过调用来实现EventpreventDefault 方法.如果在事件流的任何阶段进行一次或多次EventListeners呼叫preventDefault,则将取消默认操作.

例子

在以下示例中,单击Web浏览器中的超链接将触发事件的流(执行事件侦听器)和事件目标的默认操作(打开新选项卡).

HTML:

<div id="a">
  <a id="b" href="http://www.google.com/" target="_blank">Google</a>
</div>
<p id="c"></p>
Run Code Online (Sandbox Code Playgroud)

JavaScript的:

var el = document.getElementById("c");

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
}

function capturingOnClick2(ev) {
    el.innerHTML += "A event capture<br>";
}

function bubblingOnClick1(ev) {
    el.innerHTML += "DIV event bubbling<br>";
}

function bubblingOnClick2(ev) {
    el.innerHTML += "A event bubbling<br>";
}

// The 3rd parameter useCapture makes the event listener capturing (false by default)
document.getElementById("a").addEventListener("click", capturingOnClick1, true);
document.getElementById("b").addEventListener("click", capturingOnClick2, true);
document.getElementById("a").addEventListener("click", bubblingOnClick1, false);
document.getElementById("b").addEventListener("click", bubblingOnClick2, false);
Run Code Online (Sandbox Code Playgroud)

例1:它导致输出

DIV event capture
A event capture
A event bubbling
DIV event bubbling
Run Code Online (Sandbox Code Playgroud)

示例2:添加stopPropagation()到函数中

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
    ev.stopPropagation();
}
Run Code Online (Sandbox Code Playgroud)

结果输出

DIV event capture
Run Code Online (Sandbox Code Playgroud)

事件监听器阻止了事件的进一步向下和向上传播.但是它并没有阻止默认操作(新的选项卡打开).

例3:添加stopPropagation()到函数中

function capturingOnClick2(ev) {
    el.innerHTML += "A event capture<br>";
    ev.stopPropagation();
}
Run Code Online (Sandbox Code Playgroud)

或功能

function bubblingOnClick2(ev) {
    el.innerHTML += "A event bubbling<br>";
    ev.stopPropagation();
}
Run Code Online (Sandbox Code Playgroud)

结果输出

DIV event capture
A event capture
A event bubbling
Run Code Online (Sandbox Code Playgroud)

这是因为两个事件侦听器都在同一事件目标上注册.事件监听器阻止了事件的进一步向上传播.但是,它们并未阻止默认操作(新选项卡打开).

例4:preventDefault()例如,添加到任何函数

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
    ev.preventDefault();
}
Run Code Online (Sandbox Code Playgroud)

阻止新标签打开.

  • 感谢捕获和冒泡之间的更深层次的区别,而另一个答案只解决了jQuery问题. (23认同)
  • @Mahi是什么?我只是说事实,接受的答案是使用不是由OP承担的jQuery,所以对我来说这不是真正的答案.现在这只是技术事实,没有任何个人,也没有人会被冒犯. (3认同)
  • 您的回答非常系统,很好地演示了正在发生的事情。最初,我不想打扰您,也不想自己更改您的答案,因为我认为为清晰起见可以有所改进。这个答案向初学者解释了事件模型,因此,我认为我们可以为初学者提供的每一点帮助都将走很长一段路。[我的编辑建议已被拒绝](http://stackoverflow.com/review/suggested-edits/15850686),我不同意这种说法。如果您@Ashkan认为这些小的更改可以帮助改善答案,请合并它们。 (2认同)

Kev*_*att 62

返回false;


return false; 当你打电话时,你会做3件事:

  1. event.preventDefault() - 它会停止浏览器的默认行为.
  2. event.stopPropagation() - 它可以防止事件传播(或"冒泡")DOM.
  3. 停止回调执行并在调用时立即返回.

请注意,此行为与普通(非jQuery)事件处理程序不同,其中,特别是,return false不会阻止事件冒泡.

的preventDefault();


preventDefault(); 做一件事:它停止了浏览器的默认行为.

什么时候使用它们?


我们知道他们做了什么但是何时使用它们?这完全取决于你想要完成什么.使用preventDefault();,如果你想"只是"防止默认浏览器的行为.使用return false; 当您想要阻止默认浏览器行为并阻止事件传播DOM时.在大多数情况下你会使用return false; 你真正想要的是什么preventDefault().

例子:


让我们尝试用例子来理解:

我们将看到纯JAVASCRIPT示例

例1:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>
Run Code Online (Sandbox Code Playgroud)

运行上面的代码,你会看到超链接'点击这里访问stackoverflow.com'现在如果你点击该链接首先你会得到javascript警报链接点击下一步你会得到javascript警告div点击并立即你将被重定向到stackoverflow.com.

例2:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.preventDefault();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>
Run Code Online (Sandbox Code Playgroud)

运行上面的代码你会看到超链接'点击这里访问stackoverflow.com'现在,如果你点击该链接首先你会得到javascript警报链接点击下一步你会得到javascript警告div点击下一步你会看到超链接'点击此处访问stackoverflow.com'替换为文本'Click event prevent',您将不会被重定向到stackoverflow.com.这是由于我们用来阻止触发默认点击操作的event.preventDefault()方法.

例3:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.stopPropagation();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>
Run Code Online (Sandbox Code Playgroud)

这一次,如果你单击链接,函数executeParent()将不会被调用,你将不会得到javascript警报div 这次点击.这是因为我们使用event.stopPropagation()方法阻止了传播到父div.接下来,您将看到超链接'点击此处访问stackoverflow.com'替换为文本'Click事件将被执行',并立即将您重定向到stackoverflow.com.这是因为我们没有阻止使用event.preventDefault()方法触发此次默认点击操作.

例4:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.preventDefault();
    event.stopPropagation();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('Div Clicked');
  }
</script>
Run Code Online (Sandbox Code Playgroud)

如果单击链接,则不会调用函数executeParent(),也不会获得javascript警报.这是因为我们使用event.stopPropagation()方法阻止了传播到父div.接下来,您将看到超级链接'Click here to visit stackoverflow.com'替换为文本'Click event prevent',您将不会被重定向到stackoverflow.com.这是因为我们使用event.preventDefault()方法阻止了此次触发的默认单击操作.

例5:

对于返回false,我有三个例子,所有似乎都做了完全相同的事情(只是返回false),但实际上结果是完全不同的.以下是上述每一个实际发生的情况.

案例:

  1. 从内联事件处理程序返回false会阻止浏览器导航到链接地址,但它不会阻止事件通过DOM传播.
  2. 从jQuery事件处理程序返回false会阻止浏览器导航到链接地址,并阻止事件通过DOM传播.
  3. 从常规DOM事件处理程序返回false绝对没有任何意义.

将看到所有三个例子.

  1. 内联返回false.

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='return false'>Click here to visit stackoverflow.com</a>
</div>
<script>
  var link = document.querySelector('a');

  link.addEventListener('click', function() {
    event.currentTarget.innerHTML = 'Click event prevented using inline html'
    alert('Link Clicked');
  });


  function executeParent() {
    alert('Div Clicked');
  }
</script>
Run Code Online (Sandbox Code Playgroud)

  1. 从jQuery事件处理程序返回false.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <a href='https://stackoverflow.com'>Click here to visit stackoverflow.com</a>
</div>
<script>
  $('a').click(function(event) {
    alert('Link Clicked');
    $('a').text('Click event prevented using return FALSE');
    $('a').contents().unwrap();
    return false;
  });
  $('div').click(function(event) {
    alert('Div clicked');
  });
</script>
Run Code Online (Sandbox Code Playgroud)

  1. 从常规DOM事件处理程序返回false.

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
    return false
  }

  function executeParent() {
    alert('Div Clicked');
  }
</script>
Run Code Online (Sandbox Code Playgroud)

希望这些例子清楚.尝试在html文件中执行所有这些示例,看看它们是如何工作的.


Jun*_*aid 21

event.preventDefault()
阻止浏览器的默认行为(例如打开链接),但不会阻止事件在 DOM 中冒泡。

event.stopPropagation()
防止事件在 DOM 中冒泡,但不会停止浏览器的默认行为。

返回假;
通常出现在 jQuery 代码中,它可以防止浏览器的默认行为,防止事件在 DOM 中冒泡,并立即从任何回调中返回。

看看这篇非常好又简单的 4 分钟读物,其中包含上述文章的示例。


Vla*_*adL 16

这是这里的引用

Event.preventDefault

preventDefault方法可防止事件执行其默认功能.例如,您可以在A元素上使用preventDefault来停止单击该元素离开当前页面:

//clicking the link will *not* allow the user to leave the page 
myChildElement.onclick = function(e) { 
    e.preventDefault(); 
    console.log('brick me!'); 
};

//clicking the parent node will run the following console statement because event propagation occurs
logo.parentNode.onclick = function(e) { 
    console.log('you bricked my child!'); 
};
Run Code Online (Sandbox Code Playgroud)

虽然元素的默认功能是砖块化的,但事件继续冒泡DOM.

Event.stopPropagation

第二种方法stopPropagation允许事件的默认功能发生但阻止事件传播:

//clicking the element will allow the default action to occur but propagation will be stopped...
myChildElement.onclick = function(e) { 
    e.stopPropagation();
    console.log('prop stop! no bubbles!'); 
};

//since propagation was stopped by the child element's onClick, this message will never be seen!
myChildElement.parentNode.onclick = function(e) { 
    console.log('you will never see this message!'); 
};
Run Code Online (Sandbox Code Playgroud)

stopPropagation有效地阻止父元素知道其子元素上的给定事件.

虽然一个简单的停止方法允许我们快速处理事件,但重要的是要想一想你想要冒泡到底是什么.我敢打赌,所有开发人员真正想要的是90%的时间都是preventDefault!错误地"停止"事件可能会导致许多麻烦; 您的插件可能无法正常工作,您的第三方插件可能会被堵塞.或者更糟糕的是 - 您的代码破坏了网站上的其他功能.


小智 5

event.preventDefault();停止发生元素的默认操作。

event.stopPropagation();防止事件在 DOM 树中冒泡,从而防止任何父处理程序收到该事件的通知。

例如,如果某个链接在 a 内部附加了 click 方法DIV,或者FORM也附加了 click 方法,则它将阻止DIVFORMclick 方法触发。


Nay*_*ian 5

Event.preventDefault - 停止浏览器默认行为。现在什么是浏览器默认行为。假设您有一个锚标记,它有一个 href 属性,并且该锚标记嵌套在一个有单击事件的 div 标记内。锚标记的默认行为是当单击锚标记时它应该导航,但 event.preventDefault 的作用是在这种情况下停止导航。但它永远不会阻止事件的冒泡或事件的升级,即

<div class="container">
 <a href="#" class="element">Click Me!</a>
</div>

$('.container').on('click', function(e) {
 console.log('container was clicked');
});

$('.element').on('click', function(e) {
  e.preventDefault(); // Now link won't go anywhere
  console.log('element was clicked');
});
Run Code Online (Sandbox Code Playgroud)

结果将是

“元素被点击”

“容器被点击”

现在 event.StopPropation 它停止事件冒泡或事件升级。现在用上面的例子

$('.container').on('click', function(e) {
  console.log('container was clicked');
});

$('.element').on('click', function(e) {
  e.preventDefault(); // Now link won't go anywhere
  e.stopPropagation(); // Now the event won't bubble up
 console.log('element was clicked');
});
Run Code Online (Sandbox Code Playgroud)

结果将是

“元素被点击”

有关更多信息,请参阅此链接 https://codeplanet.io/preventdefault-vs-stoppropagation-vs-stopimmediatepropagation/