2012-01-08 67 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

相关问题