当前位置: 首页 > news >正文

JavaScript DOM 操作与事件处理全解析

内容概要:

本篇文章介绍了JavaScript DOM 中的基础概念和相关的操作。其中操作包括五种获取元素的方法、常见的事件机制(鼠标事件和键盘事件),以及对元素的相关操作:对元素内容的操作,对元素属性的操作,对表单元素的操作,对CSS样式的操作。还有大量的代码示例,和文字描述,文章的字数有14000字左右,花费了大量时间,欢迎大家一起学习和进步,最后大家喜欢的话给小宁留下关注和点赞哦!

引言:JavaScript 与网页交互的核心

在现代网页开发中,JavaScript 作为前端交互的灵魂,其与 HTML 文档的交互主要通过 DOM(Document Object Model)实现。DOM 不仅是浏览器对网页的内部表示,更是开发者通过代码操作页面的桥梁。本文将深入解析 DOM 文档对象模型、事件机制及元素操作的核心知识,帮助你掌握前端交互开发的关键技能。

1.1 什么是 DOM?

DOM(Document Object Model)是 HTML 和 XML 文档的编程接口,它将文档解析为一个由节点组成的树状结构,允许开发者通过 JavaScript 动态操作网页的内容、结构和样式。简单来说,DOM 就是浏览器对网页的一种 "对象化" 表示,就像将一本图书拆解成章节、段落、句子等层级结构,每个部分都可以被独立访问和修改。

DOM 的核心作用

  • 将 HTML 文档转换为可编程的对象结构
  • 提供标准化的 API 用于操作页面元素
  • 实现 JavaScript 与 HTML 之间的动态交互

1.2 DOM 树

DOM 树是由文档中的所有元素、属性、文本等构成的一种树状结构。它是 DOM 的核心表示形式,每个节点代表文档中的一个部分。以下是 DOM 树的主要组成部分:

  • 根节点:在 HTML 文档中,<html> 标签是 DOM 树的根节点,它是整个文档的起始点。
  • 元素节点:每个 HTML 标签对应一个元素节点,如 <head><body><div> 等。元素节点可以包含其他元素节点,形成嵌套结构。
  • 属性节点:每个标签的属性(如 idclasssrc 等)作为一个属性节点,它们总是被包含在元素节点中。
  • 文本节点:包含在标签之间的文字内容作为文本节点,例如 <p>Hello, World!</p> 中的 “Hello, World!” 就是一个文本节点。

下面是一个简单的 HTML 示例及其对应的 DOM 树结构:

关键节点类型

  • 根节点:整个 DOM 树的顶层节点,HTML 文档中为 <html> 标签
  • 元素节点:对应 HTML 标签,如 <div><p> 等
  • 属性节点:标签的属性,如 idclass 等
  • 文本节点:标签内的文字内容,如 <p>Hello</p> 中的 "Hello"

1.3、获取元素

1.3.1 常用获取元素的方法

在操作 DOM 之前,我们需要先获取到要操作的元素。以下是几种常用的获取元素的方法:

方法名称描述返回类型
document.getElementById(id)根据指定的id属性值获取唯一的元素单个元素(Element)
document.getElementsByClassName(className)根据指定的class名称获取一组元素类数组对象(HTMLCollection)
document.getElementsByTagName(tagName)根据指定的HTML标签名获取一组元素类数组对象(HTMLCollection)
document.querySelector(selector)使用CSS选择器语法匹配第一个符合条件的元素单个元素(Element)
document.querySelectorAll(selector)使用CSS选择器语法匹配所有符合条件的元素类数组对象(NodeList)

document.getElementById(id)

  • 作用:根据元素的唯一 id 属性获取单个元素
  • 返回值:单个元素对象(若不存在则返回 null)
  • 推荐场景:已知元素唯一标识时使用
<body><div id="mybox">我爱学javascript!</div><div id="mybox1">我爱学Python!</div><script>let mybox_elment = document.getElementById('mybox');console.log(mybox_elment,typeof mybox_elment)</script>
</body>

document.getElementsByClassName(className)

  • 作用:根据类名获取一组元素
  • 返回值:类数组对象(HTMLCollection)
  • 注意:返回的是动态集合,会随文档变化自动更新
<body>
<p class="myClass">我是一个p标签</p>
<p class="myClass">我是一个p标签</p>
<p class="myClass">我是一个p标签</p>
<a href="" class="isa">我是a标签</a>
<script>let myClass_elm = document.getElementsByClassName('myClass')console.log(myClass_elm)for(let i = 0;i<myClass_elm.length;i++){console.log(myClass_elm[i])}
</script>
</body>

 

document.getElementsByTagName(tagName)

  • 作用:根据标签名获取一组元素
  • 返回值:类数组对象(HTMLCollection)
  • 示例:获取页面中所有 <a> 标签
<body>
<ul class="nav" id = "nav1"><li>我是帅哥列表!</li><li>我是帅哥列表!</li><li>我是帅哥列表!</li>
</ul>
<ul class="nav" id = "nav2"><li>我是美女列表!</li><li>我是美女列表!</li><li>我是美女列表!</li>
</ul>
<script>let nav_elm = document.getElementsByTagName('ul')console.log(nav_elm)let li_elm = nav_elm[0].getElementsByTagName('li')console.log(li_elm)for(let i = 0;i<li_elm.length;i++){console.log(li_elm[i])}
</script>
</body>

④ document.querySelector(selector)

  • 作用:使用 CSS 选择器匹配第一个符合条件的元素
  • 返回值:单个元素对象(若不存在则返回 null)
  • 推荐场景:需要灵活选择器时使用
<body>
<ul class="nav" id = "nav1"><li>我是帅哥列表!</li><li>我是帅哥列表!</li><li>我是帅哥列表!</li>
</ul>
<ul class="nav" id = "nav2"><li>我是美女列表!</li><li>我是美女列表!</li><li>我是美女列表!</li>
</ul>
<script>let first_nva = document.querySelector('.nav')console.log(first_nva)let first_li = document.querySelector('.nav li')console.log(first_li)
</script>
</body>

document.querySelectorAll(selector)

  • 作用:使用 CSS 选择器匹配所有符合条件的元素
  • 返回值:类数组对象(NodeList)
  • 优势:支持所有 CSS 选择器,且返回静态集合
<body>
<ul class="nav" id = "nav1"><li>我是帅哥列表!</li><li>我是帅哥列表!</li><li>我是帅哥列表!</li>
</ul>
<ul class="nav" id = "nav2"><li>我是美女列表!</li><li>我是美女列表!</li><li>我是美女列表!</li>
</ul>
<script>let li_all = document.querySelectorAll('.nav li')for (let i = 0;i<li_all.length;i++){console.log(li_all[i])}
</script>
</body>

 

1.3.2 获取元素的注意事项

  1. 类数组与数组的区别

    • 类数组(如 HTMLCollection、NodeList)拥有索引和 length 属性,但没有数组方法(如 push()forEach()
    • 转换方法:Array.from(collection) 或 [...collection]
  2. 性能优化要点

    • 频繁获取元素时可缓存结果,避免重复查询
    • querySelectorAll() 返回静态集合,比 getElementsByClassName() 更适合需要稳定数据的场景
    • 复杂选择器(如多层嵌套)可能影响性能,尽量简化选择器

1.3.3 总结:DOM 元素获取的最佳实践

  • 优先使用 document.getElementById() 和 document.querySelector()/querySelectorAll(),因其兼容性和灵活性更优
  • 了解不同方法的返回值类型(单个元素 vs 类数组),避免类型错误
  • 合理利用选择器语法(如 #id.classelement[attribute] 等),提高选择效率

二、事件机制

2.1 事件概述

事件是用户或浏览器执行某种操作时触发的行为,例如点击按钮、滚动页面、键盘输入等。JavaScript 通过事件驱动模型实现与用户的交互 —— 当事件发生时,预先绑定的事件处理程序会被自动执行。

常见事件场景

  • 用户操作:点击、滚动、输入
  • 页面状态:加载完成、尺寸变化、错误发生
  • 设备交互:触摸、手势、方向变化

2.2 事件三要素

要成功绑定并执行一个事件,必须具备以下三个要素:

  1. 事件源:触发事件的对象(如按钮、输入框、页面等)
  2. 事件类型:触发的事件种类(如 clickkeydownload
  3. 事件处理程序:事件发生时执行的代码逻辑(通常是一个函数)

2.3 绑定事件的两种方式

方式一:直接赋值(on 事件)

<body>
<button id="btn1">按钮1</button>
<button id="btn2">按钮2</button>
<button id="btn3">按钮3</button>
<script>
// ①获取事件源(DOM 元素)
let btn1 = document.getElementById('btn1');
let btn2 = document.getElementById('btn2');
let btn3 = document.getElementById('btn3')
// ②注册事件监听器(绑定事件)
// ③编写事件处理函数
btn1.onclick = function () {alert('单击了按钮1');
};
btn2.ondblclick = function () {alert('双击击了按钮2');
}
btn3.onmouseover = function () {alert('鼠标移到了按钮3上');
}
</script>
</body>

方式二:addEventListener () 方法(推荐)

<body>
<button id="btn2">点击我</button>
<script>
// JavaScript 代码
const btn2 = document.getElementById("btn2");
btn2.addEventListener("click", function() {alert("通过 addEventListener 绑定事件");
});// 添加多个事件处理程序
btn2.addEventListener("click", function() {console.log("第二个事件处理程序");
});// 移除事件(需使用命名函数)
const handleClick = function() {console.log("可移除的事件处理程序");
};
btn2.addEventListener("click", handleClick);
btn2.removeEventListener("click", handleClick); // 移除事件
</script>
</body>

两种方式的对比

特性onclick 方式addEventListener 方式
绑定多个事件不支持(后绑定会覆盖前一个)支持(可添加多个处理程序)
事件捕获 / 冒泡阶段无法指定可通过第三个参数指定
兼容性所有浏览器IE9+(IE8 及以下使用 attachEvent)

2.4 常见鼠标事件(重点)

事件名描述典型应用场景
click鼠标单击元素时触发按钮点击、链接跳转
dblclick鼠标双击元素时触发图片放大、文本选中
mousedown鼠标按键按下时触发拖拽开始、绘制交互
mouseup鼠标按键释放时触发拖拽结束、操作完成
mousemove鼠标在元素上移动时触发鼠标跟随效果、地图导航
mouseover鼠标移入元素(包括子元素)时触发菜单悬停显示、元素高亮
mouseout鼠标移出元素(包括子元素)时触发菜单隐藏、高亮消失

 示例:鼠标事件综合应用

<body>
<div id="mouseAction" style="width: 200px; height: 200px; background-color: #ffffff;">鼠标移动过来呀
</div>
<script>let mouseAction = document.getElementById('mouseAction');let count = 0// 鼠标进入mouseAction.onmousemove = function () {this.style.backgroundColor = 'skyblue'this.textContent='鼠标已进入!'}// 鼠标离开mouseAction.onmouseout = function () {this.style.backgroundColor = 'white'this.textContent='鼠标已离开!'}// 鼠标点击mouseAction.addEventListener('click', function() {count++;this.textContent = `点击次数:${count}`;
});
</script>
</body>

2.5 常见键盘事件(重点)

事件名描述典型应用场景
keydown键盘按键按下时触发(包括功能键)输入验证、快捷键操作
keypress键盘字符键按下时触发(不包括功能键)文本输入监听、输入法支持
keyup键盘按键释放时触发输入完成确认、快捷键释放处理

示例:键盘事件获取按键信息

<body>
<input  type="text" id="shuru" placeholder="请输入:">
<p id = "keyboard">按下键盘查看按键信息</p>
<script>let input = document.getElementById('shuru');let keyboard = document.querySelector('#keyboard')input.addEventListener('keydown',function (e){keyboard.textContent = `按键码:${e.keyCode},键名:${e.key}`// 阻止默认行为(比如按下enter键提交)if(e.keyCode ===13){e.preventDefault()alert('已阻止Enter提交的默认行为')}})
</script>
</body>

三、操作元素

3.1 改变元素内容

1. textContent:纯文本内容操作

  • 作用:获取或设置元素的纯文本内容
  • 特点:不解析 HTML 标签,只输出文本内容
<body>
<div id = "box1">这是 <strong>文本</strong> 内容</div><script>// 获取内容let divText = document.getElementById('box1').textContent;console.log(divText); // 输出:这是 文本 内容// 设置内容document.getElementById('box1').textContent = '这是新的纯文本内容';let newdivText = document.getElementById('box1').textContent;console.log(newdivText);</script>
</body>

2. innerText:可见文本内容操作

  • 作用:获取或设置元素的可见文本内容
  • 特点:受 CSS 样式影响(如 display: none 的文本不会被获取)
<body>
<div id="innerTextDiv" style="font-size: 20px;">可见文本 <span style="display: none;">隐藏文本</span>
</div>
<script>
const innerText = document.getElementById("innerTextDiv").innerText;
console.log(innerText); // 输出:可见文本 (隐藏文本被忽略)
</script>
</body>

3. innerHTML:HTML 内容操作

  • 作用:获取或设置元素包含的 HTML 内容
  • 特点:解析 HTML 标签,可动态插入结构
<body>
<div id="htmlDiv">初始内容</div>
<div id="htmlDiv2">这是 <strong>文本</strong> 内容</div>
<script>// 获取内容const htmlDiv2 = document.getElementById("htmlDiv2");console.log(htmlDiv2.innerHTML);  // 这是 <strong>文本</strong> 内容// 设置内容document.getElementById("htmlDiv").innerHTML = `<h3>动态标题</h3><ul><li>列表项1</li><li>列表项2</li></ul>`;
</script>
</body>

 3.2 元素属性操作

①获取/设置/移除元素的标准属性:

 element.getAttribute('属性名')

 element.setAttribute('属性名', '属性值')

 element.removeAttribute('属性名')

<body>
<a href="https://baidu.com" id="link" title="链接描述" class="nav-link">百度一下</a>
<script>// 获取属性let a_element = document.getElementById("link");const href = a_element.getAttribute("href")const title = a_element.getAttribute("title")const class_name = a_element.getAttribute("class")console.log(`地址是:${href},链接是:${title},类名是:${class_name}`);// 设置属性a_element.setAttribute("title","百度一下")    // 修改title属性为:百度一下console.log(a_element.getAttribute("title"));  //  输出:百度一下// 移出属性console.log(a_element.getAttribute('class'));   //输出:nav-linka_element.removeAttribute("class")console.log(a_element.getAttribute("class"));   //输出:null
</script>
</body>


②直接访问常用属性: src, href, id, className, style 等

<body>
<a href="https://baidu.com" id="link" title="链接描述" class="nav-link">百度一下</a>
<script>let a_element = document.querySelector("#link");console.log(`网址是:${a_element.href},\nid是:${a_element.id}, title是:${a_element.title},类名是:${a_element.class}`);
</script>
</body>

<body>
<img src="../images/ldh.png" id="myimg" class="firstimg" alt="图片">
<script>let img = document.getElementById("myimg");// 直接访问属性console.log(`图片的地址:${img.src},id是:${img.id}`)console.log(`图片的类名:${img.class},描述是:${img.alt}`)// 修改属性// img.src = "../images/zxy.png"img.alt = "新图片"
</script>
</body>

③综合案例:实现点按钮切换图片

<body>
<img src="../images/zxy.png" title="我是张学友" id = 'myimg' style="width: 200px">
<button id = 'zxy'>张学友</button>
<button id = 'ldh'>刘德华</button>
<script>let zxybtn = document.getElementById('zxy');let ldhbtn = document.getElementById('ldh');let img = document.querySelector('#myimg');zxybtn.onclick = function () {img.setAttribute('src','../images/zxy.png')img.setAttribute('title','我是张学友')console.log(`地址是:${img.src} \n图片描述是:${img.title}`)}ldhbtn.onclick = function () {img.setAttribute('src','../images/ldh.png')img.setAttribute('title','我是刘德华')console.log(`地址是:${img.src} \n图片描述是:${img.title}`)}
</script>
</body>

 

3.3 表单元素属性操作

1. 输入框与单选框:value 属性

<body>
<form action="" method="get"><input type="text" name="username" id="username"><input type="password" name="password" id="password"><input type="submit" value="登录" id = "submitBtn"><input type="radio" name="sex" class="sex" value="男" checked>男<input type="radio" name="sex" class="sex" value="女" >女
</form>
<script>let username = document.getElementById("username");let password = document.getElementById("password");let submitBtn = document.getElementById("submitBtn");let sex = document.getElementsByClassName("sex")[0];submitBtn.addEventListener("click", function (e) {e.preventDefault();console.log(`用户名:${username.value}`);console.log(`密码:${password.value}`);if (sex.checked){console.log(`性别:${sex.value}`);}else{console.log(`性别:女`);}});
</script>
</body>

 2.复选框和下拉框:checked属性

<body>
<form action="" method="get"><input type="checkbox" name="hobby" class="hobby" value="看电影" checked>看电影<input type="checkbox" name="hobby" class="hobby" value="看小说">看小说<input type="checkbox" name="hobby" class="hobby" value="看游戏">看游戏<select name="city" id="city"><option value="北京">北京</option><option value="上海">上海</option></select><input  type="button" value="提交" id="submitBtn">
</form>
<script>let checkbox  = document.getElementsByClassName('hobby');let subbtn = document.getElementById('submitBtn');let select = document.getElementById('city');subbtn.onclick = function (e) {// 获取复选框选中项let selectedHobbies = [];for (let i = 0; i < checkbox.length; i++) {if (checkbox[i].checked) {selectedHobbies.push(checkbox[i].value);}}// 获取下拉框选中项let selectedCity = select.value;// 输出到控制台console.log('选中的爱好:', selectedHobbies);console.log('选择的城市:', selectedCity);}
</script>
</body>

  3. 禁用与只读状态

<body>
<input type="text" id="disabledInput" disabled>
<input type="text" id="readonlyInput" readonly value="只读内容">
<script>// 动态设置禁用状态const disabledInput = document.getElementById("disabledInput");disabledInput.disabled = false; // 启用输入框// 动态设置只读状态const readonlyInput = document.getElementById("readonlyInput");readonlyInput.readOnly = false; // 取消只读
</script>
</body>

3.4 样式属性操作

1. 行内样式操作:element.style

<body>
<div id="box" style="height: 100px;width: 100px;background-color: #0be4d5">样式操作实例
</div>
<button  id="btn">修改样式</button>
<script>const box = document.getElementById("box");const btn = document.getElementById("btn");btn.onclick = function () {// 修改样式box.style.width = "200px";box.style.height = "200px";box.style.backgroundColor = "#d1bfc5";// 设置新样式box.style.fontFamily = "宋体";box.style.fontSize = "20px";box.style.color = "#5440ff";box.style.border = "5px solid #5440ff";// 获取样式console.log(box.style.width);}
</script>
</body>

2. 类名操作:className 与 classList(推荐) 

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>操作元素</title>
</head><style>.base-style {width: 200px;height: 200px;border: 1px solid #040303;}.active1{width: 100px;height: 100px;background-color: #28cccf;font-family: "汉仪中黑 197";color: #f30a58;}.active2{width: 300px;height: 300px;background-color: #ff7e8b;font-size: 30px;color: #5440ff;}
</style><body><div id="classDiv" class="base-style">类样式操作</div>
<button id = "classBtn1">覆盖原样式,使用active1</button>
<br>
<button id = "classBtn2">添加样式,使用active2(遵循css的继承和覆盖)</button>
<br>
<button id = "classBtn3">删除样式</button>
<br>
<button id = "classBtn4">实现active1和active2的切换</button><script>let classDiv = document.getElementById('classDiv');let button1 = document.getElementById('classBtn1');let button2 = document.getElementById('classBtn2');let button3 = document.getElementById('classBtn3');let button4 = document.getElementById('classBtn4');button1.onclick = function () {// 方式一:使用 className(会覆盖原有类名)classDiv.className = 'active1';}button2.addEventListener('click', function () {// 方式二:使用 classList(不会覆盖原有类名)classDiv.classList.add('active2');})button3.addEventListener('click', function () {// 方式二:使用 classList(不会覆盖原有类名)classDiv.classList.remove('active2');  // 删除类名classDiv.classList.remove('active1');  // 删除类名})button4.addEventListener('click', function () {// 方式二:使用 classList(不会覆盖原有类名)classDiv.classList.add('active1');classDiv.classList.toggle('active2')  //切换类名})
</script></body>
</html>

 

3.总结:

样式操作方式对比:

操作方式核心语法优点
行内样式(style)element.style.属性 = 值1. 直接修改,即时生效
2. 可动态计算样式值(如 JS 变量)
类名操作(className)element.className = '类名1 类名2'1. 样式与逻辑分离,符合 CSS 规范
2. 可批量修改多个样式
类名操作(classList)element.classList.方法(类名)1. 提供专用 API,操作更安全
2. 支持添加 / 移除 / 切换 / 检查类名

 classList常用方法详解:

方法名参数返回值功能描述
add(className)类名字符串向元素添加指定类名,若已存在则不重复添加
remove(className)类名字符串从元素移除指定类名,若不存在则无操作
toggle(className)类名字符串布尔值切换类名:存在则移除,不存在则添加,返回操作后的状态(是否存在)

总结:DOM 与事件开发的核心要点

1. DOM 操作的核心思维

  • 树状结构思维:将 HTML 文档视为由节点组成的树,通过父子、兄弟关系导航元素
  • 选择器优先级:优先使用 querySelector/querySelectorAll,灵活处理复杂选择场景
  • 性能意识:减少频繁 DOM 操作,批量修改元素样式(如使用类名而非逐个样式修改),避免大规模重排重绘

2. 事件开发的最佳实践

  • 事件委托:将事件绑定在父元素上,通过 event.target 处理子元素事件,减少事件绑定数量
  • 事件对象:熟练使用 event 对象获取事件信息(如鼠标位置、键盘按键、事件源等)
  • 兼容性处理:了解不同浏览器的事件机制差异(如 IE 中的 attachEvent),使用库或封装函数统一处理

3. 元素操作的黄金法则

  • 内容操作:根据需求选择 textContent(纯文本)或 innerHTML(HTML 结构)
  • 属性操作:标准属性使用 getAttribute/setAttribute,常用属性直接访问
  • 样式操作:优先使用类名操作(classList),分离样式与逻辑,便于维护

通过掌握 DOM 操作、事件机制和元素操作这三大核心技能,你将能够开发出交互流畅、体验出色的网页应用。在实际开发中,建议结合框架(如 React、Vue)进一步提升开发效率,但底层的 DOM 与事件知识始终是前端开发的根基。

http://www.xdnf.cn/news/1005877.html

相关文章:

  • BeanUtil.copyProperties()进行属性拷贝时如何忽略NULL值——CopyOptions配置详解
  • 高效管理Python环境:Miniforge、pyenv和Poetry深度对比与应用
  • 建筑业应用:机器人如何改变未来建筑业发展方向
  • 介绍一下 TCP方式程序的通讯,服务器机与客户机
  • 使用 DeepSeek 为 TDengine 创建专属知识库
  • 部署安装maven和mvnd
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | RandomChoicePicker(标签生成)
  • 西门子PLC读取梅安森风压传感器数据
  • 【2025】深度学习环境搭建记录
  • inet_addr()和inet_aton()函数详解
  • 【log4j2】将运行时变量注入日志、附性能对比与生产案例(动态日志实战)
  • JFLASH 提示license 配置操作 Sorry,no valid license for I-Flash found.
  • Trae重磅升级
  • Python 字典
  • 第六节 工程化与高级特性-TS配置选项解析
  • AUTOSAR图解==>AUTOSAR_TR_InteroperabilityOfAutosarTools
  • Rust 通用代码生成器:莲花,红莲尝鲜版三十六,哑数据模式图片初始化功能介绍
  • 测试完成的标准是什么?
  • Vue3项目与桌面端(C++)通过Websocket 对接接口方案实现
  • 【源码+文档+调试讲解】自习室系统
  • HALCON第二讲->预处理
  • vue中的doSave()方法
  • Excel大厂自动化报表实战(互联网金融-数据分析周报制作上)
  • 桥接模式(Bridge Pattern)
  • FastDFS
  • Flash数据写入及ECC纠错关键函数:Fapi_issueProgrammingCommand()
  • 【微软RDP协议】微软RDP协议技术架构特点与跨地域应用实践
  • Qt 环境搭建全流程详解:从下载到创建首个项目
  • 服务器部署普罗米修斯监控CentOS8
  • 2025 TechViz 新功能:3D协作,技术进化,体验升级