在jQuery中使用.delegate

时间:2011-04-11 16:05:48

标签: jquery delegatecommand

我有一个功能,可以很好地创建我需要的事件日历的自定义工具提示。问题是,当用户点击日历上的下个月时,会生成一组新链接,jQuery不再选择这些链接。

这是我原来的功能:

jQuery(function(){
        var tip = jQuery("#tip");
        var myTitle = "";

        jQuery(".eventful-pre a, .eventful a").hover(function(e){

        toolTip = "<ul>";
           jQuery.each(jQuery(this).attr("title").split(","),function(ind, val){
               toolTip  = toolTip +"<li>"+val +"</li>";
            });
            toolTip = toolTip +"</ul>";

            tip.html(toolTip);
            myTitle = jQuery(this).attr("title");

            jQuery(this).attr("title", "");

            tip.css("top",(e.pageY+5)+"px")
                .css("left",(e.pageX+5)+"px")
                .fadeIn("slow");

        }, function() {
                jQuery("#tip").fadeOut("fast");

                jQuery(this).attr("title", myTitle);
        });

它的工作原理就是我想要的。我认为.delegate是我想要在它们出现时抓住新元素的方法,但我可能做错了因为它不起作用。

jQuery("table").delegate("a.em-calnav", function(){
        in here I pasted my previous function.
    }

日历可以在http://dev.adabible.org/about-ada/

看到

我必须做错了.delegate错误,而且必须有更好的方法来处理事情,而不是再次粘贴我的函数并在同一个脚本中使用它两次。

提前谢谢哦明智的人!

2 个答案:

答案 0 :(得分:2)

jQuery的delegate方法实际上分配了一个事件监听器。您使用了jQuery("table").delegate(...),因此您告诉jQuery为页面上的每个表分配一个事件侦听器。

所以第一步是找出你想要听的事件。你正在做工具提示,所以目前你正在使用“悬停”。没错,除了“悬停”实际上是两个事件:“mouseenter”和“mouseleave”。您可以将“悬停”与delegate一起使用,但前提是您只有一个功能来处理“进入”和“离开”事件。看起来你正在使用两个不同的功能:一个用于构建/淡入工具提示,另一个用于销毁它。

你可以使用delegate两次,一次用于“输入”,一次用于“离开”,除了(according to this comment on jQuery)所有浏览器实际上都不支持。 (QuirksMode has a good set of compatibility tables regarding "enter"/"leave", and an explanation of why they're awesome.

所以看起来你必须使用“mouseover”“mouseout”,这些因为事件冒泡的原因而变得更加复杂。但!如果您只在简单链接上使用工具提示(例如,a元素包含文本而没有其他内容,或者只有一个图像而没有其他内容),那么事情应该没问题。

下一步需要了解event bubbling, another subject that QuirksMode explains really well。将鼠标移到元素上时,会触发“mouseover”事件。如果该元素具有“mouseover”事件侦听器,则执行该事件。 事件然后向上移动到元素的父级。如果父级具有“mouseover”事件侦听器,则 也会执行。这一直持续到事件经过每个父母,一直到document

因此,当您使用delegate时,您需要告诉jQuery您实际上在寻找哪些元素。如果您正在等待一个“鼠标悬停”事件,该事件源自a元素,其类别为“悬停”,那么您将使用以下内容:

jQuery(document).delegate('a.hover', 'mouseover', ...);

请注意,第一部分可以是包含所有a.hover元素的任何内容。这些都可以大致相同:

jQuery('body').delegate('a.hover', 'mouseover', ...);
jQuery(document).delegate('a.hover', 'mouseover', ...);
jQuery('div.some_container').delegate('a.hover', 'mouseover', ...);

我提出这个问题的原因是因为在你当前的函数中,你使用选择器".eventful-pre a, .eventful a"。但后来,当您尝试授权时,您使用了"a.em-calnav"。您真正想要定位哪些选择器?如果所有可能具有工具提示的链接也具有“em-calnav”类,那么我会继续使用它,因为您不必为后代选择器而烦恼。但任何一个都是有效的。

所以我们最终得到的是这样的:

jQuery(function () {
    var tip = jQuery("#tip");
    var myTitle = "";

    jQuery("table").delegate("YOUR_SELECTOR", "mouseover", function (e) {
        var toolTip = "<ul>";
        jQuery.each(jQuery(this).attr("title").split(","), function (ind, val) {
            toolTip = toolTip + "<li>" + val + "</li>";
        });
        toolTip = toolTip + "</ul>";

        tip.html(toolTip);
        myTitle = jQuery(this).attr("title");
        jQuery(this).attr("title", "");

        tip.css("top", (e.pageY + 5) + "px")
            .css("left", (e.pageX + 5) + "px")
            .fadeIn("slow");

    }).delegate("YOUR_SELECTOR", "mouseout", function () {
        jQuery("#tip").fadeOut("fast");
        jQuery(this).attr("title", myTitle);
    });
});

您的问题是,当加载新日历时,链接不再具有“悬停”事件侦听器。此解决方案将事件委托给table。但是,如果在构建新日历的过程中,您还构建了一个新表,那么此解决方案实际上并没有做任何事情。您必须将事件委托给表的父级或其他内容。基本上,您委托了JavaScript没有真正改变的元素。 (这就是document"body"在事件委托中如此常见的原因。)

另外,我并没有真正改变功能本身;我把它们搬到了合适的地方。但有一些事情你可以做得更有效率。我看到的最大问题是你构建工具提示的方式。您可以执行以下操作,而不是调用jQuery.each

var toolTip = "<ul>";
myTitle = jQuery(this).attr("title");

toolTip += "<li>" + myTitle.split(",").join("</li><li>") + "</li></ul>";

希望我能够提供帮助。祝你好运。

答案 1 :(得分:1)

首先想到的是,您未能为委托指定事件。

您应该使用它:

jQuery("table").delegate("a.em-calnav", 'click', function(){
    in here I pasted my previous function.
}

请注意添加的click(应该是您要委派的任何事件)。