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

时间:2011-05-11 11:45:19

标签: javascript events preventdefault stoppropagation

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

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

为什么两者兼而有之?我应该继续检查两者吗?或者实际上是否存在差异?

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

7 个答案:

答案 0 :(得分:880)

stopPropagation阻止事件冒泡事件链。

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

假设你有

<div id="foo">
 <button id="but" />
</div>

$("#foo").click(function() {
   // mouse click on div
});

$("#but").click(function(ev) {
   // mouse click on button
   ev.stopPropagation();
});

示例

$("#but").click(function(event){
  event.preventDefault();
 });


$("#foo").click(function(){
 alert("parent click event fired !");
});
<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>

$("#but").click(function(event){
  event.stopPropagation();
 });


$("#foo").click(function(){
 alert("parent click event fired !");
});
<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>

使用stopPropagation仅调用按钮点击处理程序 divs点击处理程序永远不会触发。

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

以下是来自MDNMSDN

的DOM事件对象的一些文档

<强> MDN:

对于IE9和FF,你可以使用preventDefault&amp; stopPropagation。

支持IE8并将stopPropagation替换为cancelBubble并将preventDefault替换为returnValue

答案 1 :(得分:206)

术语

来自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一次电话即可进一步阻止   鼓泡。

事件取消

  

取消是通过致电Event&#39> preventDefault来完成的   方法。如果有一个或多个EventListeners来电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);

Example 1:它会产生输出

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

Example 2:将stopPropagation()添加到函数

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

导致输出

DIV event capture

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

Example 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

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

Example 4:将preventDefault()添加到任何功能,例如

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

阻止新标签打开。

答案 2 :(得分:55)

返回false;

当你打电话时,

return false;分别做三件事:

  1. event.preventDefault() - 它会停止浏览器的默认行为。
  2. event.stopPropagation() - 它可以阻止事件传播(或“冒泡”)DOM。
  3. 停止回调执行并在调用时立即返回。
  4. 请注意,此行为与普通(非jQuery)事件处理程序不同,其中,return false不会阻止事件冒泡。

    <强>的preventDefault();

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

    何时使用?

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

    <强>示例:

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

    我们将看到纯粹的JAVASCRIPT示例

    示例1:

    &#13;
    &#13;
    <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>
    &#13;
    &#13;
    &#13;

      

    运行上面的代码,你会看到超链接'点击这里访问   stackoverflow.com'现在,如果您先点击该链接,您将获得   javascript提醒链接点击接下来,您将获得javascript   警告 div单击,您将立即重定向到   stackoverflow.com。

    示例2:

    &#13;
    &#13;
    <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>
    &#13;
    &#13;
    &#13;

      

    运行上面的代码,你会看到超链接'点击这里访问   stackoverflow.com'现在,如果你先点击该链接,你会得到   javascript提醒链接点击接下来,您将获得javascript   警告 div单击接下来,您将看到超链接'点击此处   访问stackoverflow.com'替换为文本'Click事件被阻止'   您将重定向到stackoverflow.com。这是因为&gt; to event.preventDefault()方法我们用来防止默认点击   要触发的行动。

    示例3:

    &#13;
    &#13;
    <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>
    &#13;
    &#13;
    &#13;

      

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

    示例4:

    &#13;
    &#13;
    <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>
    &#13;
    &#13;
    &#13;

      

    如果单击Link,则函数executeParent()将不会   被叫,你不会得到javascript警报。这是由于我们   防止使用传播到父div   event.stopPropagation()方法。接下来,您将看到超链接'Click   这里访问stackoverflow.com'替换为文本'Click事件   阻止',你不会被重定向到stackoverflow.com。这个   是因为我们阻止了触发默认点击操作   这次使用event.preventDefault()方法。

    示例5:

      

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

    例:

    1. 从内联事件处理程序返回 false 会阻止浏览器导航到链接地址,但它不会阻止事件通过DOM传播。
    2. 从jQuery事件处理程序返回 false 会阻止浏览器导航到链接地址,并阻止事件通过DOM传播。
    3. 从常规DOM事件处理程序返回 false 绝对没有任何作用。
    4. 将会看到所有三个例子。

      1. 内联返回false。
      2. &#13;
        &#13;
        <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>
        &#13;
        &#13;
        &#13;

        1. 从jQuery事件处理程序返回 false
        2. &#13;
          &#13;
          <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>
          &#13;
          &#13;
          &#13;

          1. 从常规DOM事件处理程序返回false。
          2. &#13;
            &#13;
            <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>
            &#13;
            &#13;
            &#13;

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

答案 3 :(得分:15)

这是here

的引用

<强> 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%的时间!错误地&#34;停止&#34;一个事件可能会导致你   无数的麻烦;你的插件可能无法正常工作   第三方插件可能会被砖砌。或者更糟 - 你的代码   打破网站上的其他功能。

答案 4 :(得分:1)

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

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

例如,如果在DIVFORM内附加了点击方法的链接也附加了点击方法,则会阻止DIV或{{ 1}}点击触发方法。

答案 5 :(得分:0)

Event.preventDefault-停止浏览器默认行为。现在是什么是浏览器默认行为。假设您有一个定位标记,并且具有href属性,并且该定位标记嵌套在具有click事件的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');
});

结果将是

“元素被点击”

“已单击容器”

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

结果将是

“元素被点击”

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

答案 6 :(得分:-3)

&#13;
&#13;
$("#but").click(function(event){
console.log("hello");
  event.preventDefault();
 });


$("#foo").click(function(){
 alert("parent click event fired !");
});
&#13;
<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>
&#13;
&#13;
&#13;