
正如摘要所述,在使用 JavaScript 操作 DOM 时,经常会遇到动态创建元素后无法立即获取的问题。 典型场景是,通过 fetch 请求获取数据,然后使用 insertAdjacentHTML 将数据渲染到页面上。 然而,如果尝试在数据渲染完成之前使用 querySelector 获取这些新创建的元素,往往会失败。
问题的核心在于 JavaScript 的执行机制。insertAdjacentHTML 方法将 HTML 字符串插入到 DOM 中,这是一个异步过程。这意味着,即使代码紧随其后使用 querySelector 尝试获取新插入的元素,这些元素可能尚未完全渲染到页面上。因此,querySelector 无法找到这些元素,返回 null 或空集合。
针对上述问题,我们提供以下两种解决方案:
1. 利用 Promise 链式调用:
如果使用 fetch 方法获取数据,可以利用 Promise 的链式调用特性,确保在数据渲染完成后再执行获取元素的操作。
首先,修改 fill 函数,使其返回一个 Promise 对象:
export const fill = function (brand) {
return fetch(`./data/${brand}.json`)
.then(function (response) {
return response.json();
})
.then(function (data) {
let products = [...data.products];
products.forEach(product => {
row.insertAdjacentHTML(
'afterbegin',
` <a class="catalog__link" href="#" >
<div class="catalog__product">
<div class="catalog__product-img">
<img class="catalog__productImg" src=${product['img-src']} alt="" srcset="" />
</div>
<h3 class="catalog__product-model">${product['model']}</h3>
<p class="catalog__product-brand">${product['brand']}</p>
<span class="catalog__product-price">${product['price']}</span>
</div></a>`
);
});
});
};然后,在 loadContent.js 文件中,使用 .then() 方法链式调用 productSave 函数:
import { fill } from './fillCatalog.js';
import { productSave } from './productSave.js';
fill('jordans').then(productSave);这样,productSave 函数只有在 fill 函数中的 fetch 请求成功完成,并且数据渲染到页面上之后才会执行,从而确保 querySelector 能够找到新创建的元素。
2. 使用轮询检测机制:
如果无法修改 fill 函数,或者不确定元素何时渲染完成,可以使用轮询检测机制。该机制通过定时器定期检查目标元素是否存在,一旦找到目标元素,就执行相应的操作。
以下是一个示例代码:
function waitForElement(selector) {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
clearInterval(interval);
reject(`Element "${selector}" not found within 10 seconds.`);
}, 10000); // 设置超时时间为 10 秒
const interval = setInterval(() => {
const element = document.querySelectorAll(selector);
if (element.length > 0) {
clearInterval(interval);
clearTimeout(timeout);
resolve(element);
}
}, 200); // 每 200 毫秒检查一次
});
}
export const productSave = function () {
waitForElement('.catalog__link')
.then(links => {
links.forEach(link => {
link.addEventListener('click', e => {
let productItem = link.querySelector('.catalog__product');
const newProduct = new Product(
productItem.querySelector('.catalog__productImg').src,
productItem.querySelector('.catalog__product-model').textContent,
productItem.querySelector('.catalog__product-brand').textContent,
productItem.querySelector('.catalog__product-price').textContent.replace(/\D/g, '')
);
localStorage.setItem('newCard', JSON.stringify(newProduct));
});
});
})
.catch(error => {
console.error(error); // 处理超时或元素未找到的情况
});
};在这个示例中,waitForElement 函数接受一个 CSS 选择器作为参数,并返回一个 Promise 对象。该 Promise 对象会在找到目标元素时 resolve,或者在超时后 reject。
在 productSave 函数中,我们使用 waitForElement 函数来等待 .catalog__link 元素出现。一旦找到这些元素,就执行相应的操作。
动态创建元素后无法立即获取是 JavaScript 开发中常见的问题。通过理解问题的根本原因,并选择合适的解决方案,可以有效地解决这个问题。 本文提供的两种解决方案,Promise 链式调用和轮询检测机制,各有优缺点,可以根据实际情况选择使用。 同时,需要注意超时时间、性能影响和事件委托等问题,以确保代码的稳定性和效率。
以上就是使用 querySelector 无法获取动态创建的元素?原因与解决方案的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号