如果父 hasClass() 防止默认 link

Prevent default on link if parent hasClass()

简化HTML:

<ul>
    <li class="no-link"><a>Should not be clickable</a>
        <ul>
            <li><a>Should be clickable</a></li>
            <li><a>Should be clickable</a></li>
        </ul>
    </li>
</ul>

Javascript:

jQuery(document).ready(function( $ ) {

    $('a').parent().click(function(e) {
        if($(this).hasClass('no-link')){
            e.preventDefault();
        }
    });
})

在不应点击的 link 上工作正常,但也会影响两个后代 a 标签。为什么?我以为 parent() 只在 DOM 中向上移动了一步。

我正在通过 WordPress 以编程方式添加 class(作为外观 > 菜单控制面板中的一个选项),因此直接通过 class 定位 a 标签并不是真的一个选项。

您想要的是实际捕获对 a 元素的点击,然后检查其中的父元素 class。

只需将您的代码更改为:

$('a').click(function(e) {
     if($(this).parent().hasClass('no-link')){
         e.preventDefault();
     }
});

"I thought parent() only traversed up a single step in the DOM."

确实如此。但是您将点击处理程序附加到父级,点击事件从被点击的项目通过它们的父级、父级的父级等冒泡,并且可以沿着该链的任何地方被取消。因此,您的代码取消了该父元素内所有锚点的所有点击。

试试这个:

$('a').click(function(e) {
   if($(this).parent().hasClass('no-link')){
     e.preventDefault();
   }
});

即在锚点级别处理点击事件,测试被点击项的父级。

    $('li > a').click(function(e) {
        if($(this).parent().hasClass('no-link')){
            console.log('parent has class no-link')
            e.preventDefault()
        }
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
    <li class="no-link"><a href="#">Should not be clickable</a>
        <ul>
            <li><a href="#">Should be clickable</a></li>
            <li><a href="#">Should be clickable</a></li>
        </ul>
    </li>
</ul>

简单的解决方案是最好的 - 停止传播:

jQuery(document).ready(function( $ ) {
    $('a').parent().click(function(e) {
        e.stopPropagation(); // Preventing from event bubbling and capturing
        if($(this).hasClass('no-link')){
            e.preventDefault();
        }
    });
})