首页 文章

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

提问于
浏览
635

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

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

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

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

8 回答

  • 1

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

    Example

    $("#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 时,仅调用 buttons click handler 并且 divs click handler 永远不会触发 .

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

    以下是来自 MDNMSDN 的DOM事件对象的一些文档

    MDN:

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

    要支持IE8和更低版本,请将 stopPropagation 替换为 cancelBubble ,并将 preventDefault 替换为 returnValue

  • 15

    术语

    来自quirksmode.org

    事件捕获当您使用事件捕获时
    --------------- -----------------
    element1
    ----------- -----------
    element2 \ /
    事件捕获

    element1的事件处理程序首先触发,element2的事件处理程序最后触发 . 事件冒泡当您使用事件冒泡/
    --------------- | | -----------------
    | element1 | | |
    | ----------- | | -----------
    | | element2 | | | |
    | ------------------------- |
    |活动BUBBLING |

    element2的事件处理程序首先触发,element1的事件处理程序最后触发 . 首先捕获在W3C事件模型中发生的任何事件,直到它到达目标元素,然后再次冒泡 . | | /
    ----------------- | | - | | -----------------
    | element1 | | | | |
    | ------------- | | - | | -----------
    | | element2 \ / | | | |
    | -------------------------------- |
    | W3C活动模型|

    界面

    w3.org开始,用于事件捕获:

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

    对于事件冒泡:

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

    取消活动:

    取消是通过调用Event的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();
    }
    

    阻止新标签打开 .

  • 191

    return false;


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

    • event.preventDefault() - 它会停止浏览器的默认行为 .

    • event.stopPropagation() - 它阻止事件传播(或“冒泡”)DOM .

    • 停止回调执行并在调用时立即返回 .

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

    preventDefault();


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

    When to use them?


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

    Examples:


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

    我们将看到纯JAVASCRIPT示例

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

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

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

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

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

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

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

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

    Example 5:

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

    案例:

    • 从内联事件处理程序返回 false 会阻止浏览器导航到链接地址,但它不会阻止事件通过DOM传播 .

    • 从jQuery事件处理程序返回 false 会阻止浏览器导航到链接地址,并阻止事件通过DOM传播 .

    • 从常规DOM事件处理程序返回 false 什么都不做 .

    将看到所有三个例子 .

    • 内联返回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>
    
    • 从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>
    
    • 从常规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>
    

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

  • 825

    这是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有效地阻止父元素知道其子元素上的给定事件 .

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

  • 0

    e.preventDefault()将阻止发生默认事件,e.stopPropagation()将阻止事件冒泡并返回false将同时执行 .

    event.stopPropagation()允许执行同一元素上的其他处理程序,而event.stopImmediatePropagation()则阻止每个事件运行 .

  • 49

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

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

    例如,如果在 DIVFORM 内附加了单击方法的链接也附加了单击方法,则会阻止 DIVFORM 单击方法触发 .

  • -3

    Event.preventDefault-停止浏览器默认行为 . 现在是什么是浏览器默认行为 . 假设你有一个锚标记,它有一个href属性,这个锚标记嵌套在div标记内,该标记有一个click事件 . 锚标记的默认行为是在它应该导航的锚标记上单击时,但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/

  • 0
    $("#but").click(function(event){
    console.log("hello");
      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>
    

相关问题