动态创建元素和传递参数的事件绑定

时间:2012-01-08 00:24:10

标签: javascript jquery events closures

我在寻找问题的解决方案时发现了类似的问题,但我认为它并不是我想要的。

使用jQuery的.on()对于动态创建的元素上的事件绑定并不是很明智,但是在尝试传递不同的参数来调用不同的函数时我遇到了困难。在阅读https://developer.mozilla.org/en/JavaScript/Guide/Closures之后,我想出了以下工作示例,但我想知道它是最好的方法,还是有更优雅的解决方案?

http://jsfiddle.net/V25Zc/

另外我经常读到,由于漏洞问题,使用eval()不是最佳做法,但还有另一种方法来构建动态函数名称吗?

编辑:

非常感谢大家的回答!其中一个答案是否被删除了?我喜欢那个,因为提示将参数存储在属性中。再次感谢所有人!

5 个答案:

答案 0 :(得分: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/

答案 1 :(得分:2)

如果每个动作函数实际上必须是一个不同的函数(而不是一个函数根据传递给它的索引而有所不同),那么我就是通过在链接上放置一个属性并在其上获取它来实现的。点击您可以在此处查看的内容: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();

这也可以通过锁定索引值的执行闭包来完成,但我发现语法的可读性稍差(读取代码需要太多的脑循环并知道它在做什么)所以我更喜欢这种方式属性。

答案 2 :(得分: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')

的函数

答案 3 :(得分: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);
}

答案 4 :(得分: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();