DOM查询方法
DOM查询方法概述
DOM查询是JavaScript操作网页元素的基础,通过选择器或遍历方式获取文档中的节点对象。浏览器提供了多种原生API,现代开发中常结合CSS选择器语法进行高效定位。
document.getElementById()
通过元素ID属性获取单个节点,返回第一个匹配的DOM对象。ID在文档中应当唯一,这是最快的查询方式之一。
const header = document.getElementById('main-header');
header.style.color = '#ff0000';
注意:该方法区分大小写,且只从document对象开始搜索。
document.getElementsByClassName()
返回包含所有指定类名的元素集合(HTMLCollection),该集合是动态的会随DOM变化自动更新。
const buttons = document.getElementsByClassName('action-btn');
for (let btn of buttons) {
btn.addEventListener('click', handleClick);
}
当文档结构变化时,HTMLCollection会自动反映这些变化,但转换为数组可避免性能问题:
const btnArray = Array.from(buttons);
document.getElementsByTagName()
通过标签名获取元素集合,支持通配符"*"获取所有元素。返回的同样是动态HTMLCollection。
const images = document.getElementsByTagName('img');
console.log(`页面包含${images.length}张图片`);
document.querySelector()
使用CSS选择器语法返回第一个匹配元素,支持复杂选择器组合:
// 获取第一个类名为active的li元素
const item = document.querySelector('li.active');
// 获取data-target属性的元素
const target = document.querySelector('[data-target]');
document.querySelectorAll()
返回匹配的所有元素的静态NodeList,支持完整CSS选择器语法:
// 获取所有偶数行的表格行
const rows = document.querySelectorAll('tr:nth-child(even)');
// 复合选择器示例
const elements = document.querySelectorAll('.panel > .header, .tooltip');
与HTMLCollection不同,NodeList不会自动更新,但可以使用forEach方法遍历。
特殊集合访问
文档提供预定义集合快速访问常见元素:
document.links // 所有<a>和<area>元素
document.forms // 所有<form>元素
document.images // 所有<img>元素
document.scripts // 所有<script>元素
节点关系查询
通过现有节点进行相对查询:
const parent = element.parentNode;
const children = element.childNodes;
const firstChild = element.firstChild;
const lastChild = element.lastChild;
// 仅元素节点遍历
const prevElement = element.previousElementSibling;
const nextElement = element.nextElementSibling;
属性选择器查询
结合属性选择器进行精确匹配:
// 精确匹配属性值
const exactMatch = document.querySelector('[type="submit"]');
// 包含特定字符串
const containsMatch = document.querySelector('[class*="btn-"]');
// 开头匹配
const startsWith = document.querySelector('[href^="https"]');
// 结尾匹配
const endsWith = document.querySelector('[src$=".png"]');
表单元素查询
表单控件有专用查询方式:
const form = document.forms['login-form'];
const emailInput = form.elements.email;
const radioButtons = form.elements['newsletter'];
性能优化建议
- 缓存查询结果避免重复查询:
// 不佳做法
for(let i=0; i<100; i++) {
document.querySelector('.item').style.color = 'red';
}
// 推荐做法
const item = document.querySelector('.item');
for(let i=0; i<100; i++) {
item.style.color = 'red';
}
- 缩小查询范围:
// 在整个文档中查询
document.querySelectorAll('.item');
// 在特定容器中查询效率更高
const container = document.getElementById('app');
container.querySelectorAll('.item');
- 优先使用ID选择器,其次是类选择器
动态过滤技术
结合数组方法对查询结果进行二次处理:
// 获取所有可见的输入框
const inputs = Array.from(document.querySelectorAll('input'))
.filter(input => input.offsetParent !== null);
// 获取有data-属性的元素
const dataElements = [...document.querySelectorAll('[data-]')];
实时观察技术
使用MutationObserver监控DOM变化:
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.addedNodes.length) {
console.log('新增节点:', mutation.addedNodes);
}
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
浏览器兼容方案
处理旧版浏览器兼容问题:
// 兼容IE8的查询函数
function query(selector) {
return document.querySelectorAll ?
document.querySelectorAll(selector) :
document.getElementById(selector.slice(1));
}
// 类名查询兼容方案
function byClass(className, context) {
context = context || document;
if (context.getElementsByClassName) {
return context.getElementsByClassName(className);
}
var elements = context.getElementsByTagName('*'),
result = [];
for (var i=0; i<elements.length; i++) {
if (elements[i].className.indexOf(className) != -1) {
result.push(elements[i]);
}
}
return result;
}
复杂选择器示例
展示CSS3选择器的强大功能:
// 获取属性包含特定值的元素
const langs = document.querySelectorAll('[lang|="en"]');
// 结构伪类选择器
const thirdItem = document.querySelector('ul.items li:nth-child(3)');
// 否定伪类
const nonHidden = document.querySelectorAll('div:not(.hidden)');
// 状态伪类
const checkedItems = document.querySelectorAll('input[type="checkbox"]:checked');
自定义数据属性查询
利用data-*属性进行组件查询:
// 获取所有轮播图项
const slides = document.querySelectorAll('[data-carousel="slide"]');
// 获取特定数据值的元素
const currentSlide = document.querySelector('[data-index="3"]');
阴影DOM查询
在Web组件中查询阴影DOM内容:
const host = document.querySelector('custom-element');
const shadowInput = host.shadowRoot.querySelector('input');
动态加载内容处理
处理异步加载内容的查询策略:
// 使用事件委托处理动态内容
document.addEventListener('click', function(e) {
if (e.target.matches('.dynamic-item')) {
console.log('点击了动态加载的项目');
}
});
// 检查元素是否存在
function waitForElement(selector) {
return new Promise(resolve => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
const observer = new MutationObserver(() => {
if (document.querySelector(selector)) {
observer.disconnect();
resolve(document.querySelector(selector));
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
});
}
选择器性能比较
不同选择器的执行效率差异:
// 较快的选择器
document.getElementById('content');
document.getElementsByClassName('active')[0];
// 较慢的复杂选择器
document.querySelector('div#content ul li.active > a[href^="#"]');
错误处理机制
健壮的查询错误处理:
function safeQuery(selector, parent = document) {
try {
const el = parent.querySelector(selector);
if (!el) throw new Error(`元素未找到: ${selector}`);
return el;
} catch (error) {
console.error('查询错误:', error);
return null;
}
}
const element = safeQuery('.missing-element') || document.createElement('div');
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn