【问题标题】:JavaScript issues regarding events for dynamically created HTML有关动态创建的 HTML 事件的 JavaScript 问题
【发布时间】:2015-02-23 23:41:31
【问题描述】:

我在使用 JavaScript 定位动态创建的元素时遇到了一些问题。

问题 1

缩短的 JavaScript 代码:

var lightbox = document.createElement('div'),
    nav = document.createElement("nav"),
    imga = document.querySelectorAll(".gallery a");
for (i = 0; i < imga.length; i++) {
    imga[i].addEventListener("click", function() {
        document.body.insertBefore(lightbox, document.body.firstChild);
        lightbox.appendChild(nav);
    });
}

1: 现在我想在我的&lt;nav&gt; 上做一个活动。如何让事件定位到 #lightbox nav a 而不仅仅是 #lightbox nav

nav.addEventListener("click", function() {
    // works, but I want to target only the <a> links inside
});

我尝试了很多东西,比如:

var selector = document.querySelectorAll("nav a");
for (i = 0; i < selector.length; i++) {
    selector[i].addEventListener("click", function() {
        // doesn't work because the <nav> is inserted dynamically
    });
}

还有这个:

var selector = nav.getElementsByTagName("a");
for (i = 0; i < selector.length; i++) {
    selector[i].addEventListener("click", function() {
        // doesn't work because the <nav> is inserted dynamically
    });
}

问题 2

缩短的 JavaScript 代码:

var img,
    imga = document.querySelectorAll(".gallery a");
for (i = 0; i < imga.length; i++) {
    imga[i].addEventListener("click", function() {
            for (i = 0; i < imga.length; i++) {
                img = document.createElement("img");
                lightbox.appendChild(img);
            }
    });
}

2:如何将事件添加到动态创建的#lightbox imgimg = document.createElement("img") 必须在函数内部才能附加多个图像,因此我不能这样做(就像目前在 &lt;nav&gt; 上一样):

img.addEventListener("click", function() {
    // doesn't work because img = document.createElement("img")
    // has to be inside another function
});

有人可以帮我解决这个问题吗?我对 JavaScript 不是很有经验。

【问题讨论】:

  • 这是个好问题。 +1

标签: javascript events dynamic onclick dom-events


【解决方案1】:

问题 2

简单的解决方案是将事件处理程序添加到循环内的所有元素

var img,
    imga = document.querySelectorAll(".gallery a");

for (i = 0; i < imga.length; i++) {
    imga[i].addEventListener("click", function() {
        for (i = 0; i < imga.length; i++) {
            img = document.createElement("img");
            img.setAttribute("src", imga[i].getAttribute("href"));
            lightbox.appendChild(img);

            img.addEventListener('click', fn, false);
        }
    });
}

更难的解决方案是使用委托事件处理程序

var img,
    imga = document.querySelectorAll(".gallery a");

lightbox.addEventListener('click', function(e) {
    if ( e.target.nodeType.toLowerCase() === 'img' ) {
         // do stuff
    }
}, false);

for (i = 0; i < imga.length; i++) {
    imga[i].addEventListener("click", function() {
        for (i = 0; i < imga.length; i++) {
            img = document.createElement("img");
            img.setAttribute("src", imga[i].getAttribute("href"));
            lightbox.appendChild(img);
        }
    });
}

问题 1

可以像上面那样使用委托的事件处理程序来解决

nav.addEventListener("click", function(e) {
    if ( e.target.nodeType.toLowerCase() === 'a' ) {

         // an achor was clicked, do stuff

    }
});

【讨论】:

  • 感谢您的回复。您的“委托事件处理程序”看起来不是很优雅,没有更好的解决方案吗?而且,如果我将 e.stopPropagation()this 之类的东西放在这些 if 语句中,它们的目标是什么? this 语句等依赖于函数选择器,对吧?
  • 如果你想要更优雅,你应该仔细看看 jQuery 是如何做到的。 jQuery 在事件处理程序中将event.target 绑定为this,因此this 实际上成为动态元素等。因此可以创建看起来比仅检查nodeType 更好的便利函数。然而,原则上这正是 jQuery 和其他库所做的,它们将事件处理程序附加到父元素,依靠冒泡,然后检查 event.target 中的 DOM 树上的任何元素是否匹配某个字符串选择器等。
  • 不幸的是,我无法编写一个完整的选择器引擎和事件处理库作为答案,我只能向您展示委托事件处理程序的工作原理,并且您必须花费所有时间来制作一些东西符合您的需求。
  • 我确定确实如此。我只想要尽可能少的代码。但是,在您的第一个解决方案中,我受到启发将所有事件处理程序嵌套在第一个中,结果证明这在我的情况下非常有效(请参阅我发布的答案)。感谢您的帮助!
【解决方案2】:

就我而言,解决方案并不难。 @adeneo 让我考虑嵌套事件处理程序,结果证明它工作得很好——而且我能够使用我所有的选择器而无需修改:

var lightbox = document.createElement('div'),
    nav = document.createElement("nav"),
    imga = document.querySelectorAll(".gallery a"),
    gallery = document.getElementsByClassName("gallery"),
    img;
for (i = 0; i < imga.length; i++) {
    imga[i].addEventListener("click", function() {
        lightbox.appendChild(nav);
        document.body.insertBefore(lightbox, document.body.firstChild);
        for (i = 0; i < imga.length; i++) {
            img = document.createElement("img");
            lightbox.appendChild(img);
        }
        lightbox.addEventListener("click", function() {
            // works fine
        });
        var nava = document.querySelectorAll("#lightbox nav a");
        for (i = 0; i < nava.length; i++) {
            nava[i].addEventListener("click", function() {
                // works fine
            });
        }
        var limg = document.querySelectorAll("#lightbox img");
        for (i = 0; i < limg.length; i++) {
            limg[i].addEventListener("click", function() {
                // works fine
            });
        }
    });
}

【讨论】:

  • 接下来...Promises
  • @EddieB 我还没有读过承诺实际上是什么,它们可以在我的情况下实现吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-17
  • 1970-01-01
  • 2019-01-25
相关资源
最近更新 更多