jQuery事件委派+儿童目标帮助

时间:2009-06-15 20:18:26

标签: jquery event-delegation

我在页面上显示来自用户的一堆帖子。我有一个主要的父div,类名为'posts',每个帖子都输入一个div,里面有类名'row'。所以在div.posts里面有很多div.row。每个都看起来像这样。

<div class="row clearfix">
    <div class="left-column">
        <img src="..." title="" />
    </div>
    <div class="main-column">
        <div class="row-text">Post Text...</div>
        <div class="row-date">Posted Date...</div>
    </div>
    <div class="actions-column">
        <a href="#">Link</a>
        <a href="#">Link 2</a>
        <a href="#">Link 3 etc.</a>
    </div>
</div>

通过CSS,actions-column默认设置为display:none。当用户将鼠标悬停在帖子(div.row)上时,我想显示actions-column。我最初的做法是通过为每一行设置一个鼠标悬停,这会对浏览器产生影响并减慢速度。我做了一些研究,偶然发现了事件授权,并决定尝试一下。到目前为止,我能够确定哪一行被定位,但是,我无法弄清楚如何使用类'actions-column'来定位它的child-div。

到目前为止

代码......

$(window).load(function(){

    $('.posts').mouseover(function(e){
        var $row, $tgt = $(e.target);

        if ($tgt.hasClass("row")) {
            $row = $tgt;
        } else { 
            if ($tgt.parent().parent().hasClass('row'))
                $row = $tgt.parent().parent();

            else if ($tgt.parent().hasClass('row'))
                $row = tgt.parent();    

            else
                return false;       
        }

        //code here to select div.actions-column and show it

    });

    $('.posts').mouseover(function(e){
        var $row, $tgt = $(e.target);

        if ($tgt.hasClass("row")) {
            $row = $tgt;
        } else { 
            if ($tgt.parent().parent().hasClass('row'))
                $row = $tgt.parent().parent();

            else if ($tgt.parent().hasClass('row'))
                $row = tgt.parent();    

            else
                return false;       
        }

        //code here to select div.actions-column and hide it

    });

});

6 个答案:

答案 0 :(得分:6)

您可以使用live

$('div.row').live('mouseover', function() {
    $(this).find('div.actions-column').show();
}).live('mouseout', function() {
    $(this).find('div.actions-column').hide();
});

正如文档所述:

  

绑定“live”事件时,它将绑定到页面上的所有当前和未来元素(使用事件委派)。

还有几点说明:

  • 我发现你正在使用$(window).load()事件。您可能想要$(document).ready()
  • 你应该利用jQuery的链接功能,而不是两次查询$('.posts'),你可以在最后添加第二个调用(就像我在上面的例子中所做的那样) - 这样效率更高,是首选在jQuery中对1个选择器做多个事情的方法。
  • 您尝试编写以查找HTML树的下一个div.row的代码已经由jQuery的closest()方法实现。

你可以用它做这样的事情:

$('div.posts').hover(function(e) {
    var row = $(e.target).closest('div.row');
    $row.find('div.actions-column').show();
}, function(e) {
    var row = $(e.target).closest('div.row');
    $row.find('div.actions-column').hide();
});

但由于上面显示的live功能,这不是必需的。

  • 考虑查询的效率。如果您只有一个<div>个帖子,请考虑给它一个id属性。这是迄今为止在文档中选择元素的最有效方法,将它赋予仅出现一次的元素是有意义的。
  • 每当您按类查询元素时,最好在类之前包含标记名称(当然,除非您希望它包含在许多不同的标记中) - 所以不要寻找{{1} },养成寻找.row的习惯。它只是更快。

答案 1 :(得分:2)

我意识到这已经得到了回答,但是由于jQuery 1.5添加了一个明确的“委托”方法,现在可能是一个更好的解决方案。由于这个帖子会出现在搜索中,我会将此答案发布给其他搜索它的人。 (我还通过使用“hover”和“toggle()”而不是mouseenter / mouseleave + show()/ hide()重构进一步简洁。)

http://api.jquery.com/delegate/

$('div.row').live('mouseover', function() {
    $(this).find('div.actions-column').show();
}).live('mouseout', function() {
    $(this).find('div.actions-column').hide();
});
使用jQuery 1.5或更高版本的

可以写成:

$(".posts").delegate("div.row", "hover", function(){
    $(this).find("div.actions-column").toggle();
});

看到它的实际效果:

http://jsfiddle.net/SM6Jv/

enter image description here

答案 2 :(得分:1)

尝试使用jQuery's live()方法。它在内部使用事件委托来执行其操作,因此您甚至不必考虑正确设置事件委派。

$('.row').live('mouseover', function() {
    $(this).find('.actions-column').show();
}).live('mouseout', function() {
    $(this).find('.actions-column').hide();
});

答案 3 :(得分:0)

$('div.actions-column', $row).show(); // .hide()

<强>更新

最好使用jQuery closest([expr])

var $tgt = $(e.target);
var $row = $tgt.closest('.row');

而不是:

var $row, $tgt = $(e.target);

if ($tgt.hasClass("row")) {
    $row = $tgt;
} else { 
    if ($tgt.parent().parent().hasClass('row'))
        $row = $tgt.parent().parent();
    else if ($tgt.parent().hasClass('row'))
        $row = tgt.parent();    
    else
        return false;           
}

答案 4 :(得分:0)

尝试:

$row.find (".actions-column").hide ();

$row.find (".actions-column").show();

答案 5 :(得分:0)

除非你真的想用jQuery做这件事,否则当然可以用一行CSS来管理:

div.row:hover div.actions-column { display:block; }