JQuery Bind click событие с добавленным элементом с аргументом - PullRequest
3 голосов
/ 02 января 2011

Я пытаюсь заполнить список ul некоторыми элементами li и дать каждому элементу li ссылку, которая вызывает одну и ту же функцию с другим аргументом.Однако это, похоже, не работает, я прикрепил код ниже, CheckForNewMail вызывается при загрузке документа.Может кто-нибудь помочь мне?

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

Ответы [ 5 ]

2 голосов
/ 02 января 2011

Во-первых, я делаю предположение здесь:

  • Что вы хотите id сообщения электронной почты в этой функции клика, а не индекс, например 0, 12, 32, 5, а не 0, 1, 2, 3.

Учитывая, что (легко настроить с помощью .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);
    }
}

ЕстьНесколько изменений здесь:

  • Литералы массива, намного более простая запись
  • Правильное var объявление переменных (если они еще не определены в другом месте)
  • Использование .data() для хранения id на <a>, который мы только что создали

Затем, используя эти сохраненные данные, мы можем присоединить обработчик single на #mail-in-inbox контейнер один раз (при готовности DOM), а не на один на каждый <a> каждый раз, когда эта функция запускается, она должна выглядеть следующим образомэто:

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

Это будет отображать "Button 0 clicked!", "Button 12 clicked" и т. д. Вы можете проверить все вышеперечисленное в демонстрационной версии здесь .

2 голосов
/ 02 января 2011

Одна проблема состоит в том, что переменная i всегда будет той из последней ссылки, потому что к тому времени, когда пользователь нажимает любую ссылку, цикл завершится. Один из способов исправить это - использовать метод .data() , чтобы связать часть информации с каждым элементом li:

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

Затем вы можете привязать один обработчик событий ко всем ссылкам входящих сообщений внутри #mail-in-inbox:

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

Отредактировано, чтобы добавить: .on() была введена в jQuery 1.7. Если вы используете jQuery 1.6 или старше, используйте .delegate() или .live() (как в вопросе и оригинальной версии этого ответа).

1 голос
/ 02 января 2011

Есть пара проблем.

Во-первых, вы не используете .live().Метод .live() вызывается для объекта jQuery, которому был предоставлен селектор.Вы можете сделать это в любой момент (даже до загрузки DOM), и любые щелчки на странице, соответствующие селектору, вызовут обработчик.

В вашем случае это будет выглядеть примерно так:1008 *

В вашем случае, когда вы назначаете отдельный обработчик для каждого элемента, вы должны использовать .bind вместо live().

Как уже упоминал другой пользователь, у вас не будет правильного значения i в обработчике.Вы можете использовать $.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 );     
});

Теперь у вас будет правильное значение i в обработчике для каждого link.

0 голосов
/ 02 января 2011
   link.live('click', (function(index) {
        return function() { 
            LoadMailById(index);
        };
      )(i);
    });

Я думаю, что это должно работать, чтобы решить проблему. Анонимная функция принимает ваш аргумент i и связывает его с индексом переменной, так что когда происходит даже щелчок, она не использует значение i, оставшееся до конца цикла, а вместо этого использует его значение во время привязки.

0 голосов
/ 02 января 2011
LoadMailById(i);

i является ссылкой здесь и увеличивается на каждой итерации. Таким образом, после цикла for он содержит значение size; 4.

...