【问题标题】:How to bind function to DOM events once and only once so that they will not execute for a second time in the triggering of event?如何将函数绑定到 DOM 事件一次且仅一次,以便在事件触发时不会再次执行?
【发布时间】:2010-10-16 23:43:47
【问题描述】:

所以我有<a href='[link'] rel='Tab'> 形式的锚标记,我在页面加载时应用以下内容:(我的意思是'文档准备好')

jQuery("a[rel*=Tab]").click(function(e) {
                e.preventDefault();//then I do some stuff to open it in jq ui tab}

现在的问题是,当我这样做时,稍后通过 javascript 生成新链接,在我使用 JqGrid 加载第二页的情况下,当我第一次运行 jQuery("a[rel*=Tab]").click(function(e) 时,新的 <a rel='neoTab'> 不存在所以他们不会工作......所以我可以在每个创建新链接的事件中运行jQuery("a[rel*=Tab]").click(function(e),但是旧链接会加载多个选项卡所以有没有办法我可以选择所有的“a[rel*=Tab]”之前没有被选中?

注意:我可以并且已经通过算法方法解决了这个问题,正如您可以通过下面的详细信息看到的那样,我只是认为有一些我不知道的语法可以防止需要使用这个黑客!

不必要的细节:

var neoTabitStat = 0;
var openTabs = new Array();
openTabs[0] = 'inbox';
if(!(currentBox=='inbox'||currentBox=='outbox') ) {var currentBox = 'inbox';}

function initNeoTab(a){
    if(neoTabitStat==0) {
        jQuery("a[rel*="+a+"]").click(function(e) {
            e.preventDefault();
            tabIt(jQuery(this).attr('href')+'&nohead=1',jQuery(this).attr('title'),jQuery(this).attr('data-hovercard'));
        });
    neoTabitStat++;
    }
}

function tabIt(a,b,c) {
    c = typeof(c) != 'undefined' ? c : 0;
    lastOpen = openTabs.length;
    if(lastOpen<6) { 
        if(openTabs.indexOf(c)<0) {
            openTabs[lastOpen] = c;
            jQuery("#tabs").tabs("add" , a , b, lastOpen+1 );
        }
        $tabs.tabs('select', openTabs.indexOf(c) );
    }else{
        var tabErrDig = jQuery('<div style="display:hidden">You have opened the maximum amount of tabs please close one to open another tab.</div>').appendTo('body');
        tabErrDig.dialog({width:500,title:'Maximum Tabs Opened',modal: true,
                buttons: {
                    Ok: function() {
                        jQuery( this ).dialog( "close" );
                    }
                }
        });
    }
}

jQuery(document).ready(function() {  initNeotab('nameOfrelAttr4existingLinks'); }
myGrid = jQuery("#list").jqGrid({/*alot of stuff...*/} , gridComplete: function() { initNeotab('nameOfrelAttr4generatedLinks');
}

更新: 正如 Wrikken 建议的 jQuery().live 我检查了它,这正是我需要的,但我无法让它真正工作,在某些情况下它不会工作。对于其他编写不同解决方案的人,您是否熟悉 .live() 如果是的话,为什么我不能在这里使用它?

结论 特别感谢 fudgey、patrick dw 和 wrikken。所有答案都很有帮助。 .delegate()。为我工作,但由于某种原因.live() 没有。关于jqGrid 将元素添加到表格的方式。我会暂时保留这个问题。再次感谢您的所有帮助。向所有人 +1

【问题讨论】:

  • 你尝试了什么?能发一下代码吗?另外,&lt;a&gt; 元素是否被添加到#list 容器中?我真的建议使用.delegate()。它与.live() 相同,但将其本地化在特定容器上。这样更有效率。
  • @patrick 是的,我现在最终使用了委托,因为所有内容都被添加到#list 中。因为它是 jqGrid 正在处理的表的 id。我认为 jqGrid 中的方法会有更好的解决方案,所以我将等待 jqGrid 专家的一些答案,同时自己进行更多的研究,但到目前为止我的代码已经工作了。

标签: javascript jquery jquery-ui jqgrid


【解决方案1】:

在 jQuery 中,使用the live() function

【讨论】:

    【解决方案2】:

    "#list" 是包含动态生成的&lt;a&gt; 元素的元素吗?

    如果是这样,请使用jQuery's .delegate() method 在其上放置一个处理程序,因此在其中单击的任何'a[rel*=Tab]' 元素都会触发该处理程序。

    jQuery("#list").delegate( 'a[rel*=Tab]', 'click', function() {
        //...
    });
    

    添加到#list 的任何'a[rel*=Tab]' 元素都将自动起作用。如果#list 不是容器,则为容器使用正确的选择器。


    编辑: 虽然上面的 .delegate() 方法是(在我看来)最好的方法,但如果您确实想在创建新元素时仅将单个 click 处理程序分配给它们,您需要针对特定​​的新元素调用相同的 .click() 方法。

    所以如果你在页面加载后创建一个新的&lt;a&gt;,你会做这样的事情:

    var $newA = $('<a rel="someTab">some text</a>');
    
     // Assign click handler to only the newly created element
    $newA.click(function(e) {
           e.preventDefault();
           //then I do some stuff to open it in jq ui tab
    });
    
    $newA.appendTo('#list');
    

    当然,这不是您的确切代码,但它展示了如何创建新元素、存储对它的引用以及将 click 处理程序仅分配给该元素。

    或者,如果您要创建一个更大的结构,其中嵌套了 &lt;a&gt;,您可以执行相同的操作,但执行 .find() 以在结构中获取 &lt;a&gt;,然后分配 click

    【讨论】:

      【解决方案3】:

      我本来建议使用.one(),但您似乎是在动态添加链接。所以我最好在已经被点击的链接上添加一个标志。正如 Patrick 建议的那样,delegate 将是最好的,通过这些修改:

      jQuery("#list").delegate( 'a[rel*=Tab]', 'click', function() {
      
       if ($(this).is('.alreadyClicked')) { return false; }
       $(this).addClass('alreadyClicked');
      
       // do something 
      
      });
      

      【讨论】:

      • fudgey - 我认为问题的标题可能有点误导。通过“仅一次”,我认为 OP 指的是他正在搜索整个 DOM 以找到新创建的&lt;a&gt; 元素并分配click。因此,旧的将获得多个 click 处理程序而不是一个。我可能是错的,但这就是我从问题主体中得到的。 :o)
      • 是的,patrick 你是对的,但是 fudgey 是对的,而且他是手动做的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-29
      • 2023-03-21
      • 2020-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多