我想将侦听器添加到JavaScript中动态创建的元素中,但它似乎不起作用。它不会抛出任何错误,所以我不知道我首先要做什么。你有什么想法吗?
{
const API_KEY = "9829fe5eab6c963bbe4850df2d7de4aa";
const container = document.getElementById("container");
const flippers = document.getElementsByClassName("header__flipper");
const cityTemplate = () => {
const template = `<section class="weather">
<button class="header__flipper"><span aria-hidden="true">→</span></button>
<header class="header">
<h1 class="header__heading">dfgdfgd
</h1>
</header>
</section>`;
return template;
};
const addListeners = (collection, ev, fn) => {
for (let i = 0; i < collection.length; i++) {
collection[i].addEventListener(ev, fn, false);
}
}
const req = (id, key) => {
const url = `https://api.openweathermap.org/data/2.5/forecast?id=${id}&APPID=${key}`;
fetch(url).then((res) => {
res.json().then((data) => {
container.innerHTML += cityTemplate(data);
});
})
}
req("6695624", API_KEY);
req("6695624", API_KEY);
req("6695624", API_KEY);
addListeners(flippers, "click", () => {
alert("test");
})
}<div id="container"></div>
发布于 2017-10-13 07:42:14
问题是在fetch请求完成之前添加事件侦听器。在调用addListeners时,触发器尚未在DOM中。
我已经修改了req方法,以返回fetch的承诺。使用Promise.all,代码将等待到所有三个获取完成。这仍然不能完全解决问题,代码知道何时完成获取,但这与将req方法添加到DOM中的cityTemplate方法不同。
有两种解决办法:
setTimeout处理程序中使用Promise.all。这很可能会延迟添加事件侦听器足够长的时间,以便将模板添加到DOM中。我添加了一些console.log语句,这些语句将显示上一次呈现的日志行之前的Promise.all日志行。req方法返回您自己创建的承诺,而不是fetch承诺。在将cityTemplate添加到DOM之后,解析自创建的承诺。通过这种方式,您可以肯定地知道,在所有东西都在DOM中之前,Promise.all是不会实现的。解决方案1不是一个非常健壮的解决方案,应该避免。解决方案2提供了所需的控制类型。我的答案显示了解决方案2的基本设置,它不执行任何错误处理。
{
const API_KEY = "9829fe5eab6c963bbe4850df2d7de4aa";
const container = document.getElementById("container");
const flippers = document.getElementsByClassName("header__flipper");
const cityTemplate = () => {
const template = `<section class="weather">
<button class="header__flipper"><span aria-hidden="true">→</span></button>
<header class="header">
<h1 class="header__heading">dfgdfgd
</h1>
</header>
</section>`;
return template;
};
const addListeners = (collection, ev, fn) => {
for (let i = 0; i < collection.length; i++) {
collection[i].addEventListener(ev, fn, false);
}
}
const req = (id, key) => {
console.log(`getting ${id}`);
// Return a new promise, this promise will be fulfilled once the template
// has been added with the retrieved data.
return new Promise(resolve => {
const url = `https://api.openweathermap.org/data/2.5/forecast?id=${id}&APPID=${key}`;
// Get the data
fetch(url).then((res) => {
res.json().then((data) => {
// Add the template to the DOM
container.innerHTML += cityTemplate(data);
console.log(`rendered ${id}`);
// Relove that promise that was returned by the method.
resolve();
});
})
});
}
// Wait for all three promises to be done. These promises will be fulfilled after
// the DOM has been updated.
Promise.all([req("6695624", API_KEY), req("6695624", API_KEY), req("6695624", API_KEY)])
.then(() => {
console.log(`promise all done`);
// There is no longer a need for a timeout, due to the change to the
// req method.
addListeners(flippers, "click", () => {
alert("test");
})
});
}<div id="container"></div>
https://stackoverflow.com/questions/46723864
复制相似问题