1. JavaScript中的DOM与BOM:前端交互的基石
作为一名前端开发者,我每天都要和DOM、BOM打交道。它们是JavaScript与浏览器交互的核心接口,掌握它们意味着你能让网页"活"起来。记得我刚入行时,常常混淆这两者的区别,导致代码组织混乱。经过多年实践,我总结出了一套系统化的理解方式,今天就来分享这些经验。
DOM(Document Object Model)是文档对象模型,它把HTML文档解析为一个由节点和对象组成的结构化树形图。简单来说,DOM就是浏览器对HTML文档的编程接口,让我们可以用JavaScript来操作网页内容。而BOM(Browser Object Model)则是浏览器对象模型,提供了与浏览器窗口交互的API,比如控制浏览器导航、获取屏幕尺寸、使用定时器等。
这两者的主要区别在于:DOM关注的是文档内容本身,而BOM关注的是浏览器窗口和框架。理解这个区别很重要,它能帮助你在开发时选择正确的API。举个例子,如果你想修改某个div的内容,应该使用DOM方法;而如果你想实现页面跳转,则需要使用BOM的location对象。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. DOM操作全解析
2.1 元素获取的六种方式
获取元素是DOM操作的第一步,也是最基础的一步。在实际项目中,我通常会根据具体情况选择不同的获取方式:
javascript复制// 1. ID获取 - 最高效,返回单个元素
const header = document.getElementById('header');
// 2. 类名获取 - 返回HTMLCollection,适合批量操作
const buttons = document.getElementsByClassName('btn');
// 3. 标签名获取 - 常用于表格、列表等结构化元素
const listItems = document.getElementsByTagName('li');
// 4. name属性获取 - 常用于表单元素分组
const genders = document.getElementsByName('gender');
// 5. querySelector - CSS选择器,返回第一个匹配元素
const mainBtn = document.querySelector('.btn.primary');
// 6. querySelectorAll - 返回NodeList,支持复杂选择
const navItems = document.querySelectorAll('nav > ul > li');
经验分享:现代前端开发中,querySelector和querySelectorAll已经成为主流选择,因为它们支持CSS选择器语法,非常灵活。但在性能敏感的场景(如需要频繁操作的元素),getElementById仍然是速度最快的选择。
2.2 元素内容操作的艺术
innerText和innerHTML的区别看似简单,但在实际开发中却经常引发问题。让我用一个真实案例来说明:
javascript复制// 假设我们有一个用户评论区域
const commentDiv = document.getElementById('comment');
// 危险做法:直接使用innerHTML插入用户输入
commentDiv.innerHTML = userInput; // 可能导致XSS攻击!
// 安全做法:使用textContent或innerText
commentDiv.innerText = userInput; // 自动转义HTML标签
// 需要插入HTML时的安全做法
commentDiv.innerHTML = sanitizeHTML(userInput); // 先消毒
这里有个重要经验:当内容来自用户输入时,一定要谨慎使用innerHTML,因为它会解析其中的HTML标签,可能导致XSS攻击。我建议遵循以下原则:
- 纯文本内容优先使用innerText/textContent
- 必须使用HTML时,先进行消毒处理
- 对于完全信任的内容(如自己控制的模板),才直接使用innerHTML
2.3 属性操作进阶技巧
元素属性操作看似简单,但有些细节值得注意:
javascript复制const link = document.querySelector('a');
// 基本属性操作
link.href = 'https://example.com';
link.title = '点击访问';
// 自定义数据属性
link.dataset.trackEvent = 'outbound'; // data-track-event
// 类名操作的新方法
link.classList.add('external'); // 添加类
link.classList.remove('old-class'); // 移除类
link.classList.toggle('active'); // 切换类
// 样式操作的最佳实践
// 不推荐:直接设置style属性
link.style.color = 'red';
// 推荐:通过类名控制样式
link.classList.add('highlight');
在大型项目中,我强烈推荐使用classList而不是className来操作类名,因为它提供了更精细的控制方法(add/remove/toggle/contains),而且不会意外覆盖现有的类名。
2.4 元素创建与删除的优化实践
动态创建和删除元素是前端交互的核心能力。让我们看一个更贴近实际场景的例子:
javascript复制// 创建评论列表项的高效方式
function addComment(commentData) {
// 使用文档片段减少重绘
const fragment = document.createDocumentFragment();
const li = document.createElement('li');
li.className = 'comment';
const avatar = document.createElement('img');
avatar.src = commentData.avatar;
avatar.alt = commentData.user + '的头像';
avatar.classList.add('avatar');
const content = document.createElement('div');
content.classList.add('content');
content.innerHTML = `
<h4>${escapeHTML(commentData.user)}</h4>
<p>${escapeHTML(commentData.text)}</p>
<time>${formatDate(commentData.time)}</time>
`;
li.append(avatar, content);
fragment.appendChild(li);
// 一次性插入
