父元素a標籤的href默認行爲以及子元素綁定的click事件的響應之間存在影響

原文地址javascript

背景

開發過程當中遇到問題,簡單寫個demo 運行環境爲Chrome 68html

描述一下這個問題,當a標籤內部存在嵌套時, 父元素a標籤的href默認行爲以及子元素綁定的click事件的響應之間存在影響。頁面結構:java

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>a標籤內部點擊事件失效</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .father {
            display: block;
            width: 500px;
            height: 200px;
            background-color: rgb(210, 111, 30);
        }

        .child-one {
            display: block;
            width: 200px;
            height: 50px;
            background-color: rgb(174, 43, 226);
        }

        .child-two {
            display: block;
            width: 200px;
            height: 50px;
            background-color: rgb(43, 226, 67);
        }

        .child-three {
            display: block;
            width: 200px;
            height: 50px;
            background-color: rgb(43, 137, 226);
        }
    </style>
</head>

<body>
    <a class="father" href="father" onclick="alert(111)">父標籤
        <span class="child-one">
            子標籤1
        </span>
        <object>
            <a class="child-two" href="child-two">
                子標籤2
            </a>
        </object>
        <object>
            <a class="child-three" href="javascript:alert('href:child-three')">
                子標籤3
            </a>
        </object>
    </a>
    <script>    
        let father = document.querySelector('.father');
        let ele1 = document.querySelector('.child-one');
        let ele2 = document.querySelector('.child-two');
        let ele3 = document.querySelector('.child-three');

        ele1.addEventListener('click', function (e) {
            e.stopPropagation();
            // e.preventDefault();
            alert('click child-one')
            window.location.href = 'child-one'
        }, false)

        ele2.addEventListener('click', function (e) {
            e.stopPropagation();
            alert('click child-two')
            // window.location.href='child-two'
        }, false)

        ele3.addEventListener('click', function (e) {
            alert('click child-three')
            window.location.href = 'child-three'
        }, false)

        father.addEventListener('click', function (e) {
            alert('click father')
            window.location.href = 'father'
        }, false)

    </script>
</body>

</html>

示例以下圖(若是a標籤嵌套,瀏覽器解析錯誤,因此用object標籤包裹了一層)。git

圖1

執行操做:

  1. 當點擊父標籤時,先彈出111,而後跳轉父標籤的href連接。
    說明onclick執行先於href
  2. 當點擊child-one時,執行元素綁定的click事件,會彈出alert,可是location仍然跳轉到了father。
    阻止冒泡後,執行結果仍然不符合預期。添加preventDefault以後,執行了子元素本身的跳轉。
  3. 當點擊child-two時,彈出響應信息,而後會跳轉href的連接。
  4. 當點擊child-three時,先彈出click child-three,而後是href child-three,說明click事件先於href執行。

上面4個操做除了2以外都很好理解,2中,爲何已經在阻止了事件冒泡以後,仍然執行了父元素中href的跳轉。github

思考:

首先能夠確定的是,事件冒泡確實被阻止了,由於父元素的onclick並無執行。
因此猜想,<a>標籤的默認行爲是沒法經過取消冒泡來阻止的,就算事件沒有冒泡到父元素,子元素在父元素<a>標籤內部,仍然會執行<a>標籤默認行爲。瀏覽器

解決方法:

  • 在子元素中添加e.preventDefault()阻止默認行爲
  • 父元素不使用<a>標籤,使用其餘標籤綁定click事件且子元素阻止冒泡
  • 父元素不使用href屬性,直接在<a>標籤上綁定click事件
相關文章
相關標籤/搜索