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

Event binding on dynamically created elements and passing parameters

本文关键字:参数 事件 绑定 创建 元素 动态      更新时间:2023-09-26

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

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

http://jsfiddle.net/V25Zc/

此外,我经常读到,由于漏洞问题,使用eval()不是最佳实践,但有其他方法可以构建动态函数名吗?

编辑:

非常感谢大家的精彩回答!其中一个答案被删除了吗?我喜欢这个,因为它提示将参数存储在属性中。再次感谢大家!

事件委派的意义在于,您不需要将事件绑定到每个元素(或多次绑定到同一元素),只需将一次绑定到公共父元素,如下所示:

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/

如果每个动作函数实际上都必须是一个不同的函数(而不是一个根据传递给它的索引而不同的函数),那么我会通过在链接上放置一个属性并在单击时获取它来实现这一点,您可以在这里看到它的工作原理: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();

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

将函数放入对象中

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);
}

看起来您最初的问题是,您想要调用一个函数,该函数的名称将由传入的参数决定。这些函数在作用域中都是全局的吗?如果是这样的话,我会这么做:

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') 的函数

我个人不会麻烦创建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();