简体   繁体   English

JQuery将click事件绑定到带有参数的附加元素

[英]JQuery Bind click event to appended element with an argument

I'm trying to populate a ul list with some li elements and give each li element a link that calls the same function with a different argument. 我正在尝试使用一些li元素填充ul列表,并为每个li元素提供一个使用不同参数调用相同函数的链接。 However it doesn't seem to work, i've attached the code below, CheckForNewMail is called on document load. 但它似乎不起作用,我附上了下面的代码,在文档加载时调用CheckForNewMail。 Can anyone please help me out? 有人可以帮帮我吗?

function CheckForNewMail() {
    //////////////////////////////////////////////////////////////////
    // This will be dynamic
    MailInInbox[0] = new Array("0", "Mail One");
    MailInInbox[1] = new Array("12", "Mail Two");
    MailInInbox[2] = new Array("32", "Mail Three");
    MailInInbox[3] = new Array("5", "Mail Four");
    //////////////////////////////////////////////////////////////////////
    $('#mail-in-inbox').children().remove();

    size = 4; element = $('#mail-in-inbox');
    for(i = 0; i < size; ++i) {
        var link = $('<a href="#" class="inbox-link">'+ MailInInbox[i][1] +'</a>');
        link.live('click', function() {
            LoadMailById(i);
        });
        li = $('<li></li>');
        li.append(link);
        element.append(li);     
    }
}

function LoadMailById(id) {
    alert("Button "+ id +" clicked!");
}

One problem is that the variable i will always be that of the last link because by the time the user clicks any link, the loop would have completed. 一个问题是变量i将始终是最后一个链接的变量,因为当用户单击任何链接时,循环将完成。 One way to fix this would be to use the .data() method to associate a piece of information with each li element: 解决此问题的一种方法是使用.data()方法将一条信息与每个li元素相关联:

link.data('mailId', i); // within the loop

Then you can bind a single event handler for all inbox links inside #mail-in-inbox : 然后,您可以为#mail-in-inbox所有收件箱链接绑定单个事件处理程序:

$('#mail-in-inbox').on('click', '.inbox-link', function() {
    LoadMailById($(this).data('mailId'));
});

Edited to add: .on() was introduced in jQuery 1.7. 编辑添加: .on()在jQuery 1.7中引入。 If you are using jQuery 1.6 or older, use .delegate() or .live() (as in the question and the original version of this answer) instead. 如果您使用的是jQuery 1.6或更早版本,请使用.delegate().live() (如问题和此答案的原始版本)。

First, I'm making an assumption here: 首先,我在这里做一个假设:

  • That you want the id of the email in that click function, not the index eg 0, 12, 32, 5 , rather than 0, 1, 2, 3 . 你想要点击功能中的电子邮件的id ,而不是索引,例如0, 12, 32, 5 ,而不是0, 1, 2, 3

Given that (easy to adjust with .index() if the assumption is incorrect), you can do this: 鉴于(如果假设不正确,很容易用.index()进行调整),你可以这样做:

function CheckForNewMail() {
    MailInInbox[0] = ["0", "Mail One"];
    MailInInbox[1] = ["12", "Mail Two"];
    MailInInbox[2] = ["32", "Mail Three"];
    MailInInbox[3] = ["5", "Mail Four"];
    $('#mail-in-inbox').empty();

    var size = 4, element = $('#mail-in-inbox');
    for(i = 0; i < size; ++i) {
      $('<a href="#" class="inbox-link">'+ MailInInbox[i][1] +'</a>')
        .data('id', MailInInbox[i][0]).wrap('<li/>').parent().appendTo(element);
    }
}

There are a few changes here: 这里有一些变化:

  • Array literals, much simpler notation 数组文字,更简单的表示法
  • Proper var declaration on variables (if they aren't already defined elsewhere) 对变量进行适当的var声明(如果它们尚未在别处定义)
  • Using .data() to store the id on the <a> we just created 使用.data()id存储在我们刚刚创建的<a>

Then, using that stored data, we can attach a single handler to the #mail-in-inbox container one time (on DOM ready), rather than one to each <a> each time this function runs, it should look like this: 然后,使用存储的数据,我们可以将单个处理器的#mail-in-inbox集装箱一次 (在DOM就绪),而不是一个给每个 <a>这个函数每次运行时,它应该是这样的:

$('#mail-in-inbox').delegate('.inbox-link', 'click', function() {
  alert("Button "+ $.data(this, 'id') +" clicked!");
});

This would display "Button 0 clicked!" 这将显示"Button 0 clicked!" , "Button 12 clicked" , etc. You can test out all of the above in a demo here . "Button 12 clicked"等。 您可以在此处的演示中测试以上所有内容

There are a couple issues. 有几个问题。

First, that's not how you use .live() . 首先,这不是你如何使用.live() The .live() method is called against a jQuery object that was given a selector. 针对给定选择器的jQuery对象调用.live()方法。 You can do it at any point (even before the DOM loads), and any clicks on the page that match the selector will fire the handler. 您可以在任何时候(甚至在DOM加载之前)执行此操作,并且页面上与选择器匹配的任何单击都将触发处理程序。

In your case, it would go something like: 在你的情况下,它会像:

$('.inbox-link').live('click',function() {
   // whatever
});

In your case, where you're assign a separate handler to each item, you would use .bind instead of live() . 在您的情况下,您为每个项目分配一个单独的处理程序,您将使用.bind而不是live()

As another user mentioned, you'll not have the correct value of i in the handler though. 正如另一位用户所提到的,虽然你在处理程序中没有正确的i值。 You can use $.each() to overcome this. 您可以使用$.each()来克服这个问题。

$.each(MailInInbox, function( i ) {
    var link = $('<a href="#" class="inbox-link">'+ MailInInbox[i][1] +'</a>');
    link.bind('click', function() {
        LoadMailById(i);
    });
    $('<li></li>').append( link ).appendTo( element );     
});

Now you'll have the correct value of i in the handler for each link . 现在,您将在每个link的处理程序中拥有正确的i值。

LoadMailById(i);

i is a reference here and increased on each for-iteration. i是这里的参考,并在每次迭代时增加。 Thus, after the for loop it holds the value of size; 因此,在for循环之后它保持大小的值; 4. 4。

   link.live('click', (function(index) {
        return function() { 
            LoadMailById(index);
        };
      )(i);
    });

I think this should work to fix the problem. 我认为这应该可以解决问题。 The anonymous function takes your argument i and binds it to the variable index so that when the click even occurs, it's not using the value i leftover from the end of the loop but is instead using it's value at the time of the binding. 匿名函数接受你的参数i并将其绑定到变量索引,这样当单击甚至发生时,它不使用循环结束时的剩余值,而是在绑定时使用它的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM