将事件侦听器添加到动态创建的元素中

我目前在尝试为foreignObject使用 vanilla JS 呈现的某些s添加单击事件侦听器时遇到一些问题。


当我在点击功能上使用内置的 d3 时,它可以工作,但我更愿意使用 javascript 代码完成它。


但是,该函数永远不会为这些元素触发,我不明白为什么。


代码示例不完整,但应该突出显示我正在尝试做的事情。


var nodes = g.selectAll("foreignObject")

    .data(response.nodes)

    .enter()

    .append("foreignObject")

    .attr("x", function(d) {

        return d.x - nodeWidth / 2;

    })

    .attr("y", function(d) {

        return d.y - nodeHeight / 2;

    })

    .attr("width", nodeWidth)

    .attr("height", nodeHeight)

    .append("xhtml:div")

    .attr("class", "outer")

    .html(function(d) { 

        var nodeHtml = createNodeElement(d);

        return nodeHtml.outerHTML;

    })

   // If I append the img like this, it works, but ends up in the wrong "element scope"

   .append("img")

        .attr("class", "optionsImg")

        .attr("src","/images/options-squares.svg")

        .on("click", function(d) {

            currentTooltipObject = d;

            renderTooltipDiv();

        });



function createNodeElement(d) {

    let nodeElement = document.createElement("div");

    nodeElement.className = "nodeElement";

    let nodeOptionsImg = document.createElement("img");

    nodeOptionsImg.className = "nodeOptionsImg";

    nodeOptionsImg.src = "/images/options-squares.svg";

    nodeOptionsImg.addEventListener("click", function() {

        console.log("Clicked on optionsImg for this object: "+d);

    });

    nodeElement.appendChild(nodeOptionsImg);

    return nodeElement;

}


有只小跳蛙
浏览 133回答 2
2回答

慕仙森

您的方法的主要问题是使用outerHTML和innerHTML(由 内部使用.html())来创建/移动/复制元素有点像序列化和反序列化您的 HTML DOM 树。这适用于 HTML 元素本身,但是,它不保留事件侦听器。因此,createNodeElement在此过程中,您附加到函数中元素的侦听器将丢失。这是其他问题的变体,例如“是否可以在不破坏后代事件侦听器的情况下附加到innerHTML?” .如果您退后一步并重新阅读 D3 API文档,您会发现您实际上已经差不多了:D3 提供了将本机 DOM 节点附加到选择的方法:选择。追加(类型)<>如果指定的类型是函数,则对每个选定元素进行评估,依次传递当前数据 ( d )、当前索引 ( i ) 和当前组 ( nodes ),并将this作为当前 DOM 元素(节点[ i ])。这个函数应该返回一个要追加的元素。如果您想坚持createNodeElement使用本机 JS 方法创建元素的实现,您可以简单地将该函数传递给,selection.append()因为它返回一个新创建的节点及其<img>子节点。因此,您的代码可以简化为:var nodes = g.selectAll("foreignObject")&nbsp; &nbsp; /* styling omitted */&nbsp; .append("xhtml:div")&nbsp; &nbsp; .attr("class", "outer")&nbsp; .append(createNodeElement);因为只有对 DOM 节点的引用才会被传递到所有附加到元素的事件监听器也将被保留。

慕斯709654

在createNodeElement函数中nodeOptionsImg元素尚未呈现时执行addEventListener。侦听器只能添加到渲染元素。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript