jQuery 点击事件对于动态创建的元素无效

3
我查看了SO上的其他解决方案,但似乎没有一个能帮助我。为了让你了解一些背景,昨天我试图通过类选择所有DIV并存储它们的ID。请参阅此链接现在我已经拥有了我想要创建一些新元素并整合这些ID,以便能够单击这些新元素。我去JSFiddle展示一个演示,但疯狂的是,在那里,我的代码可以工作,但在我的应用程序(Chrome扩展)中却不能工作。更疯狂的是,我已经在其他部分实现了jQuery点击事件,而且没有问题,所以我真的很困惑为什么在这种特殊情况下它不起作用。这是在我的应用程序中无法工作的JSFiddle。感谢任何帮助!对于发布这么多(愚蠢的)问题,我很抱歉。

HTML:

<div class="HA" id="k2348382383838382133"></div>
<div class="HA" id="k2344444444444444444"></div>
<div class="HA" id="k234543544545454454"></div>
<div class="HA" id="k2346787878778787878"></div>

JS:

var HAContainer = document.querySelectorAll('.HA');
var HALength = document.querySelectorAll('.HA').length;

    var id = [];
    var j = 0;

    $('.HA').each(function(){
        id[j++] = $(this).attr('id');
    });

for (var i=0; i<HALength; i++) {

    var HABtn, HABtnImg, HAImgContainer;

    HABtnImg = document.createElement("img");
    HABtnImg.src = ("http://www.freesmileys.org/smileys/smiley-laughing002.gif"); 
    HABtnImg.className = "ha-icon"; 

    HAImgContainer = document.createElement("div");
    HAImgContainer.setAttribute("id", 'HA-'+id[i] + '-container');
    HAImgContainer.appendChild(HABtnImg);

    HABtn = document.createElement("div");
    HABtn.className = 'ha-button';
    HABtn.setAttribute("id", 'HA-container');
    HABtn.appendChild(HAImgContainer);

    HAContainer[i].appendChild(HABtn);
    HAClick(id[i]);

}

function HAClick(id) {

    $('#HA-'+id+'-container').click(function() {
        alert("clicked on ID " + id);
    });
}

3
你在那里重复使用了ID,请注意。对 HABtn 进行了如下操作:设置属性 id'HA-container',并将 HAImgContainer 添加为子元素。 - Ted
3个回答

3

为了使事件与动态添加的元素一起正常工作,您需要委托您的事件:

$('body').on("click", '#HA-'+id+'-container', function() {
    alert("clicked on ID " + id);
});

我是一位有用的助手,可以翻译文本。
我注意到了一些问题,并将通过更好的方法进行编辑:
更改为:
HABtn.setAttribute("id", 'HA-container');

致:

HABtn.setAttribute("id", 'HA-'+id[i] + '-inner-container');
HABtn.setAttribute("class", 'HA-container');

而不是:

function HAClick(id) {
    $('#HA-'+id+'-container').click(function() {
        alert("clicked on ID " + id);
    });
}

只需使用委托一次附加事件:

$('body').on("click", '.HA-container', function() {
    alert("clicked on ID " + $(this).attr('id'));
});

谢谢taxicala,终于成功了!我必须将HAClick(id[i]);从For循环中取出,以便它不会重复。我已经为此挣扎了12个小时,最后在这里寻求帮助。谢谢! - SS113
没问题!很高兴能帮忙 :) - taxicala

1
jsFiddle会自动选择你使用的JavaScript代码,并将其放置在onload事件处理程序中。

enter image description here

作为结果,你的代码将被包裹在 onload 事件处理程序中,基本上看起来像这样。
window.onload = function(){
    //your code here
};

在jsFiddle中它能够运行是因为脚本在DOM加载后执行,因此可以与DOM中的元素进行交互。可能您的Chrome扩展程序在元素加载后没有起作用。
最好将您的JavaScript代码包装在document.ready快捷方式中。
$(function(){
    //your code here
});

鉴于此,您的代码仍存在一些问题。不清楚为什么需要嵌套div结构,可能是由于css样式的结果,但一个问题是id的重复。它们可能只是类名(我正在引用“HA-container”)。
jQuery在构造函数中提供了一种非常简单的方式来创建元素,您可以在此处利用它。这将使您的代码更加流畅和易读。
此外,您可以使用.data('id',value)将所使用的id存储在容器元素的jquery对象引用中以进行数据存储。这也将允许您立即分配单击事件处理程序而无需使用另一个函数进行分配。 jsFiddle演示

$('.HA').each(function(){
    var btn = $('<div class="ha-button HA-container">');
    var cont = $('<div id="'+this.id+'-container">').data('id',this.id);
    cont.click(function(){ alert("clicked on ID " + $(this).data('id')); });
    var img = $('<img src="http://www.freesmileys.org/smileys/smiley-laughing002.gif" class="ha-icon" />');
    $(this).append(btn.append(cont.append(img)));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="HA" id="k2348382383838382133"></div>
<div class="HA" id="k2344444444444444444"></div>
<div class="HA" id="k234543544545454454"></div>
<div class="HA" id="k2346787878778787878"></div>


哇,只用了7行代码就实现了我之前40行“尝试”做的事情...感谢你的详细解释!我刚开始学习JS/jQuery,总感觉有些东西我还不懂。 - SS113

0
我会重新编写一下,以充分利用jQuery:
for (var i=0; i<HALength; i++) {

    var HABtnImg = $('<img/>')
            .attr('src', 'http://www.freesmileys.org/smileys/smiley-laughing002.gif')
            .addClass('ha-icon');

    var HAImgContainer = $('<div/>')
            .attr('id', 'HA-'+id[i] + '-container')
            .append(HABtnImg);

    var HABtn = $('<div/>')
            .addClass('ha-button')
            .append(HAImgContainer);
            //don't use duplicate ID's here

    $(HAContainer[i]).append(HABtn);
}

然后像这样附加事件:

$(document).on('click', '.ha-button', function(e){
   //your click code here 
   var id = $(this).find('div').attr('id');
   alert("clicked on ID " + id);
});

谢谢提供另一种方法,它也可以工作。您能告诉我这种方法是否比另一种方法有什么优势吗? - SS113
1
@SS113 我只是觉得这样更清晰、更易读。当jQuery被包含但实际上并没有使用时,我会感到很奇怪。回答你问题的根本答案是委托事件,这在所有答案中基本上都是相同处理方式。 - Ted

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接