javascript - Event binding on dynamically created elements and passing parameters - Stack Overflow

I found similar questions while searching for a solution for my problem but I don't think its quit

I found similar questions while searching for a solution for my problem but I don't think its quite that what I'm looking for.

Using jQuery's .on() is no brainer for binding events on dynamically created elements, but I got stuck while trying to pass different parameters to call different functions. After reading I came up with the following working example, but I would like to know if its the best way to do it or if there is a more elegant solution?

/

Plus I often read that using eval() isn't a best practice due to vulnerability issues but is there another way to build dynamic function names?

Edit:

Thanks a lot for everyone for the great answers! Did one of the answers got deleted though? I liked that one because of the hint to store the parameter in an attribute. Thanks again all!

I found similar questions while searching for a solution for my problem but I don't think its quite that what I'm looking for.

Using jQuery's .on() is no brainer for binding events on dynamically created elements, but I got stuck while trying to pass different parameters to call different functions. After reading https://developer.mozilla/en/JavaScript/Guide/Closures I came up with the following working example, but I would like to know if its the best way to do it or if there is a more elegant solution?

http://jsfiddle/V25Zc/

Plus I often read that using eval() isn't a best practice due to vulnerability issues but is there another way to build dynamic function names?

Edit:

Thanks a lot for everyone for the great answers! Did one of the answers got deleted though? I liked that one because of the hint to store the parameter in an attribute. Thanks again all!

Share Improve this question edited Jan 8, 2012 at 0:48 Bay asked Jan 8, 2012 at 0:24 BayBay 2052 silver badges14 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 3

The point of event delegation is that you don't need to bind an event to every single element (or to the same element multiple times), just once to the mon parent, like so:

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

To avoid using eval, you could have an array of functions and call them by index:

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

http://jsfiddle/V25Zc/2/

If each action function actually has to be a different function (rather than one function that acts different based on the index passed to it), then I'd do it this way by putting an attribute on the link and fetching it upon click which you can see it work here: http://jsfiddle/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();

If you don't have to have separate functions for each action, I'd do it like this which you can see here: http://jsfiddle/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();

This could also be done with an executing closure which locks in the index value, but I find that syntax somewhat less readable (it takes too many brain cycles to read the code and know what it's doing) so I prefer this way with the attribute.

Put your functions in an object

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

course if they are being made on the global scope you could also do

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

It looks like your original problem was that you wanted to call a function whose name would be determined by the parameter passed in. Are these functions all global in scope? If so, I would just do this:

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

This has the added advantage that, if you ever wanted to pass arguments to actionX, you do so by passing these arguments after index with the following modification

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

So helpCallback(1, "foo"); would return a function that calls action1('foo')

I wouldn't personally bother with creating IDs and then referencing them. Why not use closures within bindings to actual elements you've created.

For example, you can do something like

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

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745586109a4634549.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信