jQuery子元素a href单击无效

21

我有这段代码:

<html>
<head>
<title>site</title>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
    $('#wlink a').click(function() {
        $('.box:visible').fadeOut('fast', function() {
            $('#' + (this.id).replace('link', '')).fadeIn('fast');
        });
        $('#wlink a').removeClass('selected');
        $(this).addClass('selected');
    });
    $('#wlink div').click(function() {
        var child = $(this).children();
        child.click();
    });
    $('#linkbox1').addClass('selected');
    $('#box1').fadeIn('fast');
});
</script>
</head>

<style>
a { outline: none; cursor: pointer; }
#wrapper { border:1px solid #cccccc; border:solid 1px #ddd; width:806px; height:255px; overflow: hidden; }
#wrapperBox { width:6000px; }
span.text { font-size:100px; color:#aaa; }
div.box { float:left; width:805px; height:255px; background:#efefef; display: none; }
#wlink div { width: 200px; text-align:center; display: block; float:left; border: solid 1px #ddd; }
a.selected { background: #eee; }
</style>

<body>
<div id="wrapper">
    <div id="wrapperBox">
        <div id="box1" class="box">
            <span class="text">Box 1</span>
        </div>
        <div id="box2" class="box">
            <span class="text">Box 2</span>
        </div>
        <div id="box3" class="box">
            <span class="text">Box 3</span>
        </div>
        <div id="box4" class="box">
            <span class="text">Box 4</span>
        </div>
    </div>
</div>
<div id="wlink">
    <div><a id="linkbox1">Box 1</a></div>
    <div><a id="linkbox2">Box 2</a></div>
    <div><a id="linkbox3">Box 3</a></div>
    <div><a id="linkbox4">Box 4</a></div>
</div>
</body>
</html>

现在我想要做的是,当A HREF的父DIV被点击时,我想模拟一个HREF点击。但它不起作用,我得到了这个错误:

too much recursion
[Break On This Error] )});return}if(e.nodeType===3||e.nodeTy...nt=="undefined"&&(b=b.ownerDocument|| 

我的代码有什么问题?

谢谢,J

4个回答

30

sillyMunky的观点是正确的,因为您的DIV点击处理程序也会被触发,从而创建无限循环,但他解决此问题的方法不是最佳实践。您需要在单击处理程序中使用e.stopPropagation()显式停止事件传播,并不要使用return false。使用return false将做多于您需要/意图的事情。如果您还想防止默认的单击操作并停止页面跳转,您还需要添加e.preventDefault()

$('#wlink a').click(function(e) {
    e.stopPropagation();
    e.preventDefault(); //not part of fixing your issue, but you may want it.
    $('.box:visible').fadeOut('fast', function() {
        $('#' + (this.id).replace('link', '')).fadeIn('fast');
    });
    $('#wlink a').removeClass('selected');
    $(this).addClass('selected');
});

更多信息请参考:停止(误)滥用Return False


1
我认为他想要停止事件传播和阻止默认行为,最有效的方法就是返回false。此外,我个人经历过使用这两个函数时出现浏览器兼容性问题,但使用返回false却从未遇到过。我不同意使用返回false是不好的做法,某些人在博客上说它更好也不能改变我的看法。如果他需要默认操作但不需要冒泡,则正确的答案应该是使用e.stopPropagation。我更喜欢我的更优雅的答案。 - sillyMunky
指出链接中的这些事情并提供替代方案是一个好主意,也许楼主以前没有遇到过。但我认为声称有一种“最佳实践”是走弯路并不是很有帮助。 - sillyMunky
1
你假设他想要那个结果,而没有明确表达,我认为这是一种误导。新手需要理解他们的代码在做什么以及为什么要以某种方式编写它。如果OP想要return false并理解其影响,那就好。误导的是说“只需返回false以防止传播”,因为返回false不仅如此,还可能产生其他负面影响。我的意思是,“这是实现您要求的代码,这就是返回false的实际效果。请明智使用。”但实际上,这并不是什么大不了的事情。 - Adam Terlson
什么是 e.stopPropagation(); 和 e.preventDefault(); 的作用? - Tech4Wilco
1
@Jimmy - 请看我上面的链接,它解释得很清楚。也可以查看这些链接:https://developer.mozilla.org/en/DOM/event.preventDefault 和 https://developer.mozilla.org/en/DOM/event.stopPropagation - Adam Terlson
显示剩余2条评论

29

如果您不想更改您的代码,@Adam Terlson的解决方案很好。这是我的解决方案:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>site</title>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#wlink a').click(function() {
    var l = (this.id).replace('link', '');
    $('.box:visible').fadeOut('fast', function() {
        $('#' + l).fadeIn('fast');
    });
    $('#wlink a').removeClass('selected');
    $(this).addClass('selected');
});
$('#linkbox1').addClass('selected');
$('#box1').fadeIn('fast');
});
</script>

</head>

<style>
a { outline: none; }
#wrapper { border:1px solid #cccccc; border:solid 1px #ddd; width:806px; height:255px; overflow: hidden; }
#wrapperBox { width:6000px; }
span.text { font-size:100px; color:#aaa; }
div.box { float:left; width:805px; height:255px; background:#efefef; display: none; }
a.linkBox { cursor: pointer; width: 200px; text-align:center; display: block; float:left; border: solid 1px #ddd; }
a.selected { background: #eee; }
</style>

<body>

<div id="wrapper">
   <div id="wrapperBox">
       <div id="box1" class="box">
           <span class="text">Box 1</span>
       </div>
       <div id="box2" class="box">
           <span class="text">Box 2</span>
       </div>
       <div id="box3" class="box">
           <span class="text">Box 3</span>
       </div>
       <div id="box4" class="box">
           <span class="text">Box 4</span>
       </div>
   </div>
</div>
<div id="wlink">
   <a class="linkBox" id="linkbox1">Box 1</a>
   <a class="linkBox" id="linkbox2">Box 2</a>
   <a class="linkBox" id="linkbox3">Box 3</a>
   <a class="linkBox" id="linkbox4">Box 4</a>
</div>

</body>
</html>

它没有调用先前回答中的任何内容,而是使用HREF而不使用DIV,并使用CSS来实现效果。这样,您就不必选择子元素、父元素等等...


我认为这更容易理解,但我需要改变太多的代码。谢谢。 - Tech4Wilco

15
只需在锚点的点击处理程序结尾添加return false;即可。问题似乎是被触发的点击处理程序会冒泡到包含它的div中,从而造成无限递归循环。添加返回false将防止事件传播(达到上层父元素)和执行默认操作(如果单击了链接则跟随链接)。您可以使用事件对象的各个函数(e.stopPropagation和e.preventDefault),但是在目标浏览器中执行这些操作可能会导致问题,比起用return false;技术同时执行两个操作更加稳妥。
 $('#wlink a').click(function() {
    $('.box:visible').fadeOut('fast', function() {
        $('#' + (this.id).replace('link', '')).fadeIn('fast');
    });
    $('#wlink a').removeClass('selected');
    $(this).addClass('selected');
    return false;
 })

0

我认为你的问题在于你将点击事件绑定到了div和锚点上(它们都被同一个div包裹)。因此,当有人点击div或其中任何链接时,两个点击事件都会触发。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接