2012-01-08 95 views
1

我在爲我的問題尋找解決方案時發現了類似的問題,但我不認爲它相當於我正在尋找的東西。動態創建的元素和傳遞參數的事件綁定

使用jQuery的.on()對綁定動態創建的元素上的事件並不是一件容易的事,但我在試圖傳遞不同的參數來調用不同的函數時卡住了。在閱讀https://developer.mozilla.org/en/JavaScript/Guide/Closures後,我想出了下面的工作示例,但我想知道它是否是最好的方法或者是否有更優雅的解決方案?

http://jsfiddle.net/V25Zc/

另外,我經常閱讀使用eval()不是最好的做法,由於脆弱性問題,但有另一種方式來構建動態函數名?

編輯:

非常感謝每個人的偉大的答案!其中一個答案被刪除了嗎?我喜歡那個,因爲這個提示將參數存儲在屬性中。再次感謝所有!

回答

3

事件代表團的一點是,你並不需要一個事件綁定到每一個元素(或同一元素多次),只是一次普通的父母,就像這樣:

function createLinks() { 

    var $container = $("#container"), 
     links = ""; 



    for (var i=0; i < 4; i++) { 
     links += '<a class="linklink" href="#">Link_' + i + '</a>'; 
    } 

    $container.html(links).on("click", ".linklink", function(){ 
     console.log("fn action"+$(this).index()); 
    }); 
} 

createLinks(); 

爲了避免使用eval,你可以有一個函數數組,並通過指數打電話給他們:

arrayOfFunctions[ $(this).index() ](); 

http://jsfiddle.net/V25Zc/2/

+0

+1 - 這是正確的答案,我會拋出一個data-foo屬性來存儲我,但無論 – 2012-01-08 00:43:37

+0

@AdamRackis是我這樣做了純粹的懶惰 – Esailija 2012-01-08 00:55:06

+0

@Esailija非常感謝這個解決方案,因爲這樣,循環完全乾淨(內部沒有函數),甚至不需要輔助函數!:) – Bay 2012-01-08 00:59:00

1

它看起來像你最初的問題是,你想調用一個函數,它的名字將由傳入的參數決定。這些函數是否在全局範圍內?如果是的話,我只想做:

function helpCallback(index) { 
    return function() { 
     window['action' + index](); 
    } 
} 

這是,如果你想傳遞參數給actionX額外的好處,這樣做的指標合格後這些參數有以下修改

function helpCallback(index) { 
    var args = arguments; 
    return function() { 
     window['action' + index].apply(null, [].slice.call(args, 1)); 
    } 
} 

所以helpCallback(1, "foo");將返回調用action1('foo')

+0

這是行不通的,因爲'i的值'將會是4(for循環的結尾),而不是你在helpCallback(i)被實際執行時想要的值。這是人們在處理將來會被調用的函數時陷入的一個常見陷阱。這種類型的問題通常通過創建一個新的閉包來解決,這個閉包在執行for循環時被傳入。 – jfriend00 2012-01-08 00:27:37

+0

@ jfriend00 - 你在5秒鐘內寫了評論,我的回答很糟糕嗎?我最初誤解了發生了什麼,但我認爲我目前的答案是正確的。 – 2012-01-08 00:29:43

+0

問題是,'helpCallback()'返回一個函數,所以把它放到一個匿名函數中,就像你在做的事情在這裏沒有解決任何問題。我想你誤解了OP使用'helpCallback()'做的事情。 – jfriend00 2012-01-08 00:44:44

1

把你的函數對象的功能

var myFuncs = { 
action0:function(){ console.log("fn action0"); }, 
action1:function(){ console.log("fn action1"); }, 
action2:function(){ console.log("fn action2"); }, 
action3:function(){ console.log("fn action3"); } 
}; 

var funcNumber = "3"; 

for (var i=0; i < 4; i++) 
{ 
    links += '<a id="link_' + i + '" href="#">Link_' + i + '</a>'; 
    (function(myI) 
    { 
     $container.on("click", '"#link_' + i + '"', function() 
     { 
       myfuncs["action"+funcNumber](mI); 
     }); 
    })(i); 
} 

當然,如果他們正在對全球範圍內讓你也可以做

for (var i=0; i < 4; i++) 
{ 
    links += '<a id="link_' + i + '" href="#">Link_' + i + '</a>'; 
    (function(myI) 
    { 
     $container.on("click", '"#link_' + i + '"', function() 
     { 
       window["action"+funcNumber](mI); 
     }); 
    })(i); 
} 
+0

非常感謝,這絕對是避免eval()的一個好方法。 :) – Bay 2012-01-08 00:32:57

+0

添加了一個匿名封閉,如果你要在循環中使用它,以便在回調中獲得正確的「我」值 – 2012-01-08 00:34:16

0

我不會親自過問與創建ID,然後引用它們。爲什麼不在綁定到你創建的實際元素中使用閉包。

例如,你可以這樣做

function createLinks() { 

    var $container = $("#container"); 

    for (var i=0; i < 4; i++) { 
     var link = $('<a href="#link' + i + '">Link_' + i + '</a>'); 
     $container.append(link); 
     (function(){ 
      var index = i; 
      link.click(function(){ 
       alert("Do my thing " + index); 
      }); 
     })(); 
    } 

} 

createLinks(); 
+0

我不認爲這會起作用。 alert()將始終顯示i爲4(for循環結尾處的值)。 – jfriend00 2012-01-08 00:35:27

+0

該死的,jfriend00。我錯過了。現在修復,使用匿名函數閉包。 – 2012-01-08 00:51:24

2

如果每個動作功能實際上已經是一個不同的功能(而不是一個功能,基於傳遞給它的索引行爲不同),那麼我d通過在鏈接上放置一個屬性並通過點擊來獲取它,這樣做可以這樣做:http://jsfiddle.net/jfriend00/gFmvG/

function action0(){ console.log("fn action0"); } 
function action1(){ console.log("fn action1"); } 
function action2(){ console.log("fn action2"); } 
function action3(){ console.log("fn action3"); } 

var actions = [action0, action1, action2, action3]; 

function createLinks() { 

    var $container = $("#container"), 
     links = ""; 

    for (var i=0; i < 4; i++) { 
     links += '<a id="link_' + i + '" href="#" data-num="' + i + '">Link_' + i + '</a>'; 
     $container.on("click", '"#link_' + i + '"', function() { 
      actions[$(this).data("num")](); 
     }); 
    } 

    $container.html(links); 
} 

createLinks(); 

如果你不必須有單獨的函數對每一個動作,我不喜歡這樣,你可以在這裏看到:http://jsfiddle.net/jfriend00/Z8Rq6/

function doAction(index) { 
    console.log("fn action" + index); 
} 

function createLinks() { 

    var $container = $("#container"), 
     links = ""; 

    for (var i=0; i < 4; i++) { 
     links += '<a id="link_' + i + '" href="#" data-num="' + i + '">Link_' + i + '</a>'; 
     $container.on("click", '"#link_' + i + '"', function() { 
      doAction($(this).data("num")); 
     }); 
    } 

    $container.html(links); 
} 

createLinks(); 

這也可以與執行關閉其鎖定在指數值完成,但我發現語法稍差可讀(它需要太多的腦循環讀取代碼,並知道它在做什麼),所以我更喜歡這種方式的屬性。

+0

+1承諾。你真的可以檢查我的答案,以確保我沒有說什麼*其他*愚蠢? – 2012-01-08 01:11:48

+0

@ jfriend00我提高了這一點,因爲我非常喜歡這個提取屬性的想法。太糟糕了,不能同時接受兩個答案。 :( – Bay 2012-01-08 01:12:34

相關問題