jQuery click事件第一次触发,但不是第二次触发

时间:2011-01-21 21:32:17

标签: jquery click css-selectors

这是我正在使用的HTML:

<ul id="categories">
  <li><a href="#cargo">Cargo Trailers</a></li>
  <div class="dropdown">
    <ul>
      <li><a href="#utility">Utility Trailers</a></li>
    </ul>
  </div>
</ul>

我编写了一个jQuery脚本来隐藏下拉列表div。下拉div在第一次触发click事件时出现。一旦选择了dropdown div中的li并在#categories ul中切换第一个li的位置,单击li将不会显示下拉div。

这是jQuery:

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

// hide the dropdown div
$('#categories > div').hide();

/*
    Click the drop down arrow function
*/
var $listHeader = $('#categories > li');

$listHeader.click(function() {  

    if ( $('#categories > div:hidden') ) {
        //show the drop down
        $('#categories > div').show();
    } else {
        //hide the drop down
        $('#categories > div').hide();
    }
});


/*
    Click a list-item in the drop down function
*/
$('#categories > div a').click(function() {


    /* actions to change the title to the newly selected item */
    // hide the ul
    $('#categories > div').hide();

    // move the clicked item to the header
    $(this).prependTo('#categories > li');

    // move the previous title to the dropdown and sort
    $('#categories > li > a:eq(1)').prependTo('#categories > div > ul > li:empty');

    // Reset the listHeader variable
    $listHeader = $('#categories > li');

    // cancel default browser action
    return false;

});
});

3 个答案:

答案 0 :(得分:4)

这个$('#categories > div:hidden')将始终返回jQuery对象(其计算结果为true),即使没有匹配选择器的元素也是如此。使用jQuery的.toggle()代替if...else

$('#categories > div').toggle();

这里是an example

一起玩

更新以回复您的评论:已更新示例 - http://jsfiddle.net/Etkjr/1/

您是对的,事件处理程序在DOM更改时未绑定。为了防止,您需要使用2个jQuery函数:.live().delegate。当DOM被更改时,它们都监视DOM更改并将事件重新绑定到选择器。

您想要点击第一个li来展开下拉菜单 - 使用

$('#categories li:first').live('click', function() {})
这样点击第一个li会触发你的处理程序,即使你的li刚刚移到第一个位置。

$('#categories').delegate('.dropdown a', 'click', functon(evt) {})

这是.delegate()的一个例子。这意味着当有人点击.dropdown a内的#categories元素匹配时,将调用此处理程序。

此处您可以使用.live(),但.delegate更有意义。我们delegate点击单个事件处理程序,而不是将事件处理程序分配(复制)到所有匹配的元素。

我还更新了“移动”代码。这里有趣的副作用是,您不需要在第二个处理程序内.hide()下拉列表。您看,当您单击下拉列表中的链接时,链接将移动到第一个位置。 .live()会检测到并为您刚刚点击的链接指定click()处理程序。但是事件仍在传播,所以在第二个处理程序完成后,事件冒泡到li$('.li').live('click', ...)执行,隐藏你的下拉列表。

希望这是有道理的。

答案 1 :(得分:0)

可能是你的if语句需要.length,给出:

if($('selector')。length&gt; 0)  //显示下拉列表

您当前的if语句不会检查对象是否存在。选择器返回一个空的元素集合,如果它们与任何东西都不匹配,则返回null。

答案 2 :(得分:0)

也许prependTo删除了click事件处理程序。再次执行初始化。如果确实有效,您可以选择使用jQuery.live()函数而不是jQuery.click()来绑定点击事件。