jQuery 事件委托 + 儿童定位帮助

发布于 2024-07-25 11:17:11 字数 1932 浏览 5 评论 0 原文

我在页面上显示了一堆用户的帖子。 我有一个类名为“posts”的主父 div,每个帖子都输出在一个类名为“row”的 div 中。 所以 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”类来定位它的子 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

    });

});

I display a bunch of posts from users on a page. I have the main parent div with the class name 'posts' and each post is outputted in a div with class name 'row' inside of it. So there's a whole lot of div.row's inside the div.posts. Each look like this.

<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>

Via CSS the actions-column is set to display:none by default. When a user mouseover's a post (div.row) I want to show the actions-column. My initial way of doing it was by setting a mouseover even for each row and that was taking it's toll on the browser and slowing things down. I did some research and stumbled upon event delegation and decided to give it a try. So far I am able to identify which row is being targeted, however, I cannot figure out how to target it's child-div with the class 'actions-column'.

Code so far...

$(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

    });

});

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

岁吢 2024-08-01 11:17:12

我意识到这个问题已经得到了解答,但由于 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();
});

可以写成:

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

查看实际操作:

http://jsfiddle.net/SM6Jv/

输入图片此处描述

I realize this has already been answered, but since jQuery 1.5 adds an explicit "delegate" method, that might be a better solution now. Since this thread will come up in searches, I post this answer for other people searching for it. (I also refactor for further conciseness by using "hover" and "toggle()" instead of 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();
});

with jQuery 1.5 or higher could be written as:

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

See it in action:

http://jsfiddle.net/SM6Jv/

enter image description here

落墨 2024-08-01 11:17:12

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

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

Try using jQuery's live() method. It uses event delegation internally to perform its actions so you won't even have to think about setting up event delegation properly.

$('.row').live('mouseover', function() {
    $(this).find('.actions-column').show();
}).live('mouseout', function() {
    $(this).find('.actions-column').hide();
});
别低头,皇冠会掉 2024-08-01 11:17:12

尝试:

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

并且

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

Try:

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

And

$row.find (".actions-column").show();
白衬杉格子梦 2024-08-01 11:17:12

?:

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

更新:

最好使用 jQuery 最接近([expr])< /a>:

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;           
}

?:

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

UPDATE:

It is better to use jQuery closest([expr]):

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

instead of:

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;           
}
天涯离梦残月幽梦 2024-08-01 11:17:12

除非你真的想用 jQuery 来做到这一点,否则当然可以用一行 CSS 来管理某些东西:

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

Unless you really wanted to do this with jQuery then of course something can be managed with a line of CSS:

div.row:hover div.actions-column { display:block; }
后来的我们 2024-08-01 11:17:11

您可以使用 live

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

如文档所述:

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

更多注意事项:

  • 我看到您正在使用 $(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 功能。

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

You could use live:

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

As the documentation notes:

When you bind a "live" event it will bind to all current and future elements on the page (using event delegation).

A couple more notes:

  • I see you are using the $(window).load() event. You probably want $(document).ready()
  • You should take advantange of jQuery's chaining capabilities instead of querying for $('.posts') twice, you can just append the second call at the end (like I did in my example above) - this is much more efficient and the preferred way of doing multiple things to 1 selector in jQuery.
  • The code you are trying to write to find the next div.row up the HTML tree has already been implemented by jQuery's closest() method.

You could do something like this with it:

$('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();
});

But this is not necessary because of the live functionality I showed above.

  • Think about the efficiency of your queries. If you only have a single <div> with a class of posts, consider giving it an id attribute. This is by far the most efficient method of selecting elements in a document, and it makes sense to give it to elements that only occur once.
  • Whenever you are querying for an element by class, it is good practice to include the tag name before the class (unless you expect it to be in many different tags, of course) - so instead of looking for .row, make a habit of looking for div.row instead. It's just faster.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文