他们似乎在做同样的事情…… 一个是现代的,一个是古老的?还是不同的浏览器支持它们?

当我自己处理事件时(没有框架),我总是检查两者,如果存在,就执行两者。(我也返回false,但我觉得这与node.addEventListener附加的事件不起作用)。

那么为什么两者都有呢?我应该继续检查两者吗?还是真的有区别?

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


当前回答

术语

从quirksmode.org:

Event capturing When you use event capturing | | ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 \ / | | | ------------------------- | | Event CAPTURING | ----------------------------------- the event handler of element1 fires first, the event handler of element2 fires last. Event bubbling When you use event bubbling / \ ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 | | | | | ------------------------- | | Event BUBBLING | ----------------------------------- the event handler of element2 fires first, the event handler of element1 fires last. Any event taking place in the W3C event model is first captured until it reaches the target element and then bubbles up again. | | / \ -----------------| |--| |----------------- | element1 | | | | | | -------------| |--| |----------- | | |element2 \ / | | | | | -------------------------------- | | W3C event model | ------------------------------------------

接口

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

If the capturing EventListener wishes to prevent further processing of the event from occurring it may call the stopPropagation method of the Event interface. This will prevent further dispatch of the event, although additional EventListeners registered at the same hierarchy level will still receive the event. Once an event's stopPropagation method has been called, further calls to that method have no additional effect. If no additional capturers exist and stopPropagation has not been called, the event triggers the appropriate EventListeners on the target itself.

对于事件冒泡:

任何事件处理程序都可以选择通过 调用Event接口的stopPropagation方法。如果有任何 对象上的所有其他EventListener调用此方法 current EventTarget将被触发,但冒泡将在此停止 的水平。只需要调用一个stopPropagation来阻止进一步的操作 冒泡。

取消事件:

取消通过调用事件的preventDefault来完成 方法。如果一个或多个eventlistener调用preventDefault 事件流的任何阶段,默认操作都将被取消。

例子

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

HTML:

<div id="a">
  <a id="b" href="http://www.google.com/" target="_blank">Google</a>
</div>
<p id="c"></p>

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

例1:它产生输出

DIV event capture
A event capture
A event bubbling
DIV event bubbling

例2:向函数中添加stopPropagation()

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

输出中的结果

DIV event capture

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

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

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

或者函数

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

输出中的结果

DIV event capture
A event capture
A event bubbling

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

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

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

阻止打开新标签页。

其他回答

event.preventDefault ();停止元素的默认动作。

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

例如,如果在DIV或FORM中附加了一个带有单击方法的链接,它将阻止DIV或FORM单击方法被触发。

stopPropagation在捕获和冒泡阶段阻止当前事件的进一步传播。

preventDefault阻止浏览器对该事件的默认操作。

例子

preventDefault

$(" #但是”)。点击(函数(事件){ event.preventDefault () }) $ (" # foo”)。点击(函数(){ 警报(“父点击事件触发!”) }) < script src = " https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js " > < /脚本> < div id = " foo " > <按钮id = "但是" > < /按钮>按钮 < / div >

stopPropagation

$(" #但是”)。点击(函数(事件){ event.stopPropagation () }) $ (" # foo”)。点击(函数(){ 警报(“父点击事件触发!”) }) < script src = " https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js " > < /脚本> < div id = " foo " > <按钮id = "但是" > < /按钮>按钮 < / div >

使用stopPropagation,只有按钮的点击处理程序被调用,而div的点击处理程序永远不会触发。

如果你使用preventDefault,只有浏览器的默认动作被停止,但div的点击处理程序仍然会触发。

下面是一些来自MDN的DOM事件属性和方法的文档:

event.cancelBubble event.preventDefault () event.returnValue event.stopPropagation ()

对于IE9和FF,你可以只使用preventDefault和stopPropagation。

为了支持IE8和更低的版本,将stopPropagation替换为cancelBubble,将preventDefault替换为returnValue

这是这里的引语

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!'); 
};

虽然元素的默认功能是砖砌的,但事件继续在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!'); 
};

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

虽然一个简单的停止方法允许我们快速处理事件,但它是 重要的是要考虑你到底想要发生什么 冒泡。我敢打赌开发人员真正想要的是preventDefault 90%的时间!错误地“停止”事件可能导致您 无数的麻烦接踵而来;你的插件可能无法工作 第三方插件可能会被砖化。或者更糟——你的代码 破坏站点的其他功能。

返回错误;


返回错误;当你调用它时,它会做3件不同的事情:

event.preventDefault() -它会停止浏览器的默认行为。 event. stoppropagation()——它阻止事件传播(或“冒泡”)DOM。 停止回调执行并在调用时立即返回。

注意,此行为与普通(非jquery)事件处理程序不同,在普通事件处理程序中,值得注意的是,返回false不会阻止事件冒泡。

preventDefault ();


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

什么时候使用它们?


我们知道它们做什么,但什么时候使用它们?简单地说,这取决于你想要完成什么。使用preventDefault ();如果你想“只是”阻止默认的浏览器行为。使用return false;当您希望阻止默认浏览器行为并阻止事件传播DOM时。在大多数情况下,你会使用return false;你真正需要的是preventDefault()。

例子:


让我们通过例子来理解:

我们将看到纯JAVASCRIPT的例子

示例1:

< div onclick = " executeParent () " > <a href='https://stackoverflow.com' onclick='executeChild()'>点击这里访问stackoverflow.com</a> < / div > < >脚本 函数executeChild() { alert('链接点击'); } executeParent() { alert (' div点击'); } > < /脚本

运行上面的代码,你会看到超链接'点击这里访问 Stackoverflow.com '现在如果你先点击那个链接,你会得到 点击下一步,你会得到javascript 点击,你将立即被重定向到 stackoverflow.com。

示例2:

< div onclick = " executeParent () " > <a href='https://stackoverflow.com' onclick='executeChild()'>点击这里访问stackoverflow.com</a> < / div > < >脚本 函数executeChild() { event.preventDefault (); event. currenttargget . innerhtml = '点击事件已阻止' alert('链接点击'); } executeParent() { alert (' div点击'); } > < /脚本

Run the above code you will see the hyperlink ‘Click here to visit stackoverflow.com‘ now if you click on that link first you will get the javascript alert Link Clicked Next you will get the javascript alert div Clicked Next you will see the hyperlink ‘Click here to visit stackoverflow.com‘ replaced by the text ‘Click event prevented‘ and you will not be redirected to stackoverflow.com. This is due > to event.preventDefault() method we used to prevent the default click action to be triggered.

示例3:

< div onclick = " executeParent () " > <a href='https://stackoverflow.com' onclick='executeChild()'>点击这里访问stackoverflow.com</a> < / div > < >脚本 函数executeChild() { event.stopPropagation (); event. currenttargget . innerhtml = '点击事件已阻止' alert('链接点击'); } executeParent() { alert (' div点击'); } > < /脚本

This time if you click on Link the function executeParent() will not be called and you will not get the javascript alert div Clicked this time. This is due to us having prevented the propagation to the parent div using event.stopPropagation() method. Next you will see the hyperlink ‘Click here to visit stackoverflow.com‘ replaced by the text ‘Click event is going to be executed‘ and immediately you will be redirected to stackoverflow.com. This is because we haven’t prevented the default click action from triggering this time using event.preventDefault() method.

示例4:

< div onclick = " executeParent () " > <a href='https://stackoverflow.com' onclick='executeChild()'>点击这里访问stackoverflow.com</a> < / div > < >脚本 函数executeChild() { event.preventDefault (); event.stopPropagation (); event. currenttargget . innerhtml = '点击事件已阻止' alert('链接点击'); } executeParent() { alert (' Div点击'); } > < /脚本

If you click on the Link, the function executeParent() will not be called and you will not get the javascript alert. This is due to us having prevented the propagation to the parent div using event.stopPropagation() method. Next you will see the hyperlink ‘Click here to visit stackoverflow.com‘ replaced by the text ‘Click event prevented‘ and you will not be redirected to stackoverflow.com. This is because we have prevented the default click action from triggering this time using event.preventDefault() method.

例5:

对于返回false,我有三个例子,它们似乎都在做完全相同的事情(只是返回false),但实际上 结果却截然不同。这是每一个的实际情况 上面的。

例:

从内联事件处理程序返回false会阻止浏览器导航到链接地址,但它不会阻止事件通过DOM传播。 从jQuery事件处理程序返回false会阻止浏览器导航到链接地址,并阻止事件通过DOM传播。 从常规DOM事件处理程序返回false完全没有任何作用。

将看到所有三个例子。

内联返回false。

< div onclick = " executeParent () " > <a href='https://stackoverflow.com' onclick='return false'>点击这里访问stackoverflow.com</a> < / div > < >脚本 var link = document.querySelector('a'); 链接。addEventListener('点击',函数(){ event. currenttargget . innerhtml = '使用内联html阻止单击事件' alert('链接点击'); }); executeParent() { alert (' Div点击'); } > < /脚本

从jQuery事件处理程序返回false。

< script src = " https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js " > < /脚本> < div > <a href='https://stackoverflow.com'>点击这里访问stackoverflow.com</a> < / div > < >脚本 $ (' a ') .click(函数(事件){ alert('链接点击'); $ (' a ')。text('点击事件阻止使用返回FALSE'); $ (' a ') .contents () .unwrap (); 返回错误; }); $ (div) .click(函数(事件){ alert (' Div点击'); }); > < /脚本

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

< div onclick = " executeParent () " > <a href='https://stackoverflow.com' onclick='executeChild()'>点击这里访问stackoverflow.com</a> < / div > < >脚本 函数executeChild() { event. currenttargget . innerhtml = '点击事件已阻止' alert('链接点击'); 返回假 } executeParent() { alert (' Div点击'); } > < /脚本

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

事件。preventDefault-停止浏览器默认行为。现在来看看浏览器的默认行为。假设你有一个锚标签,它有一个href属性,这个锚标签嵌套在一个div标签中,这个div标签有一个点击事件。锚标签的默认行为是,当点击锚标签时,它应该导航,但什么事件。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');
});

结果将是

"元素被点击"

"容器被点击"

现在的事件。停止传播:停止事件冒泡或事件升级。现在来看上面的例子

$('.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');
});

结果将是

"元素被点击"

更多信息请参考这个链接 https://codeplanet.io/preventdefault-vs-stoppropagation-vs-stopimmediatepropagation/