DOM(文档对象模型)是 HTML/XML 文档的编程接口,通过它可动态操作网页内容、结构与样式。本文将结合示例代码,系统讲解 DOM 核心知识点(重点补充事件系统全解),并针对蓝桥杯 Web 应用开发赛道给出针对性备考建议。
一、DOM 核心知识点详解
1. DOM 元素获取
获取 DOM 元素是所有操作的基础,常用方法如下:
-
querySelector(selector):返回第一个匹配 CSS 选择器的元素,支持所有 CSS 选择器语法。 -
querySelectorAll(selector):返回所有匹配元素的NodeList 类数组,可通过 for 循环遍历。
代码示例
// 获取单个class为text的输入框
var text = document.querySelector('.text');
// 获取所有class为item的日期元素
var items = document.querySelectorAll('.item');
2. 事件系统全解(蓝桥杯核心高频考点)
事件是 DOM 交互的核心,网页的所有用户交互都基于事件机制实现,也是蓝桥杯 Web 赛道每年必考的核心内容,占比超 40%。下面从基础原理到实战应用,结合示例代码完整讲解。
2.1 事件的核心三要素
任何一个 DOM 事件都由三个核心部分组成,缺一不可:
-
事件源:触发事件的 DOM 元素(比如示例中的输入框、日期 div、可点击的 div)
-
事件类型:触发的动作类别(比如输入、点击、鼠标移入、失焦)
-
事件处理函数:事件触发后要执行的代码逻辑
结合示例代码解析:
// 事件源:class为text的input输入框
var text = document.querySelector('.text');
// 事件类型:input输入事件
// 事件处理函数:function内的逻辑
text.oninput = function(){
console.log(this.value); // 输入时实时打印输入内容
}
2.2 事件绑定的三种方式(含蓝桥杯考点对比)
蓝桥杯常考三种绑定方式的区别、适用场景与坑点,下面结合示例代码逐一讲解:
(1)HTML 行内绑定(内联事件)
直接在 HTML 标签的属性中绑定事件,格式为on事件名="执行代码/函数调用",原文第三个代码块使用了该方式:
<!-- 事件源:div,事件类型:click,处理函数:div1Click()调用 -->
<div id="dd" class="div1" onclick="div1Click()">ggx jiayou</div>
<script>
function div1Click(){
console.log('div1被点击了');
}
</script>
-
特点:HTML 与 JS 强耦合,不推荐工程化使用,但蓝桥杯简单题目中会出现
-
核心坑点 :行内绑定的函数必须是全局函数,且
this默认指向window,而非事件源元素 -
蓝桥杯考法:改错题型中,常考「行内绑定调用的函数未定义」「this 指向错误」的问题
(2)DOM0 级事件绑定(示例代码核心使用方式)
通过DOM元素.on事件名 = 处理函数的方式绑定,原文中所有的oninput/onclick/onmouseenter均为该方式:
// 给所有日期item绑定点击事件
for(var i=0;i<items.length;i++){
var item = items[i];
item.onclick = function(){
// 点击后的高亮切换逻辑
}
}
-
核心特点:
-
同一个元素的同一个事件类型,只能绑定一个处理函数,后绑定的会完全覆盖之前的
-
this指向触发事件的元素本身(和行内绑定有本质区别) -
仅支持事件冒泡阶段触发,不支持捕获阶段
-
-
解绑方式 :
元素.on事件名 = null -
蓝桥杯考法:tab 切换、高亮选中、表单输入处理等核心题型的标准写法,必须熟练掌握
(3)DOM2 级事件绑定(蓝桥杯进阶高频考点)
通过addEventListener()方法绑定,是工业级开发的标准方式,也是蓝桥杯难题的核心考点:
// 语法:元素.addEventListener(事件类型, 处理函数, 捕获/冒泡配置)
text.addEventListener('input', function(e){
console.log('输入内容:', this.value);
}, false);
-
核心特点:
-
同一个元素的同一个事件类型,可以绑定多个不同的处理函数,按绑定顺序依次执行
-
第三个参数可控制触发阶段:
false(默认,冒泡阶段)/true(捕获阶段) -
this指向事件源元素,事件对象会作为第一个参数自动传入处理函数
-
-
解绑方式 :必须使用
removeEventListener(),且处理函数必须是同一个函数引用(匿名函数无法解绑) -
蓝桥杯考法:事件委托、事件流控制、多事件绑定的复杂交互题,必考该方法
2.3 事件对象 Event(蓝桥杯必考核心)
事件触发时,浏览器会自动创建一个Event事件对象,包含了该事件的所有详细信息(比如触发的元素、鼠标位置、键盘按键等),并自动传入事件处理函数。
(1)获取方式
-
DOM0 级绑定:可通过
window.event或处理函数的第一个形参获取 -
DOM2 级绑定:通过处理函数的第一个形参获取(标准写法)
item.onclick = function(e){
// 兼容所有浏览器的写法
var event = e || window.event;
console.log(event);
}
(2)蓝桥杯高频常用属性 & 方法
|-----------------------------------|------------------------|-------------------------------|
| 事件对象成员 | 核心作用 | 蓝桥杯核心考法 |
| event.target | 触发事件的实际目标元素(最内层元素) | 事件委托的核心,必考 |
| event.currentTarget | 绑定事件的元素(和this指向完全一致) | 区分事件源与绑定元素,改错题型常考 |
| event.preventDefault() | 阻止元素的默认行为 | 表单提交阻止页面刷新、a 标签跳转阻止、右键菜单阻止,必考 |
| event.stopPropagation() | 阻止事件冒泡 / 捕获的传播 | 弹窗点击关闭、父子元素事件冲突处理,高频考点 |
| event.key / event.keyCode | 键盘事件的按键值 / 按键编码 | 回车提交表单、快捷键功能、输入限制,表单题常考 |
2.4 事件流机制(捕获→目标→冒泡)
事件流描述了事件在 DOM 树中的传播顺序,分为 3 个阶段,是理解事件行为的核心,也是蓝桥杯的难点考点:
-
捕获阶段 :事件从
window对象开始,自上而下向目标元素传播 -
目标阶段:事件到达实际触发的目标元素
-
冒泡阶段 :事件从目标元素,自下而上向
window对象传播
核心规则:
-
DOM0 级绑定、行内绑定,仅能在冒泡阶段触发事件
-
addEventListener的第三个参数为true时,在捕获阶段触发;false(默认)在冒泡阶段触发
结合示例代码的核心考点 : 示例中使用的onmouseenter/onmouseleave,和onmouseover/onmouseout的核心区别,就是是否冒泡:
-
mouseenter/mouseleave:不冒泡,仅在鼠标进入 / 离开绑定元素本身时触发,不会因为子元素触发而冒泡,完美适配示例中的日期 item 悬浮效果,不会出现误触发 -
mouseover/mouseout:会冒泡,鼠标进入 / 离开绑定元素、子元素都会触发,容易出现意外的悬浮效果,蓝桥杯改错题型常考这个坑
2.5 常用事件类型全解(结合示例代码 + 蓝桥杯考法)
下面按类别详解示例中用到的、以及蓝桥杯高频考察的事件类型,明确触发时机与核心区别:
(1)表单事件(原文第一部分代码核心)
蓝桥杯表单验证、实时搜索、输入限制题必考,示例中用到了 4 个核心表单事件:
|----------------|-------------------------------------|--------------------------------------|
| 事件名 | 触发时机 | 核心考点 |
| oninput | 输入框的值发生变化时实时触发(每输入 / 删除一个字符就触发) | 实时字数统计、实时搜索、输入内容格式化,蓝桥杯最高频表单事件 |
| onchange | 输入框失焦,且值和获焦时相比发生了变化才触发 | 表单值校验、下拉框选择处理,和oninput的触发时机区别是必考考点 |
| onfocus | 元素获得焦点时触发 | 输入框获焦时的提示文案隐藏、样式高亮 |
| onblur | 元素失去焦点时触发 | 失焦时的表单校验、输入内容格式化 |
示例代码行为解析:
// 每输入一个字符,就会触发,实时获取输入值
text.oninput=function(){
console.log(this.value);
}
// 只有输入框失焦,且内容发生了修改,才会触发
text.onchange=function(){
console.log('changed', this.value);
}
// 点击输入框,光标进入时触发
text.onfocus=function(){
console.log('get focus');
}
// 点击输入框外的区域,光标离开时触发
text.onblur=function(){
console.log('lose focus');
}
(2)鼠标事件(原文第二部分代码核心)
蓝桥杯点击交互、悬浮效果、拖拽题必考,示例中用到了 3 个核心鼠标事件:
|--------------------|-----------------------------|-----------------------------|
| 事件名 | 触发时机 | 核心考点 |
| onclick | 鼠标左键按下并松开,且在同一个元素上完成时触发 | 按钮点击、tab 切换、高亮选中,最基础的高频事件 |
| onmouseenter | 鼠标进入绑定元素本身时触发,不冒泡 | 悬浮高亮、悬浮提示,适合列表项的悬浮效果,无冒泡误触发 |
| onmouseleave | 鼠标离开绑定元素本身时触发,不冒泡 | 悬浮效果还原,和mouseenter配对使用 |
补充高频鼠标事件:
-
onmousedown/onmouseup:鼠标按下 / 松开时触发,优先级高于click,拖拽题必考 -
ondblclick:鼠标双击时触发
(3)键盘事件(蓝桥杯高频考点)
常用于搜索框回车提交、快捷键、输入限制,核心事件:
-
onkeydown:键盘按键按下时触发,按住会连续触发 -
onkeyup:键盘按键松开时触发,能获取到输入完成后的最终值 -
蓝桥杯考法:回车提交表单、数字输入限制、ESC 关闭弹窗
(4)页面 / 窗口事件(蓝桥杯坑点考点)
-
window.onload:页面所有资源(HTML、CSS、JS、图片)全部加载完成后触发 -
DOMContentLoaded:DOM 树解析完成后触发,早于onload -
蓝桥杯坑点:JS 代码写在
<head>中时,DOM 还未解析,获取元素会返回null,必须用这两个事件包裹代码
2.6 事件委托(事件代理)- 蓝桥杯超高频必考
事件委托是利用事件冒泡的特性,把多个子元素的事件绑定,统一交给父元素处理,是蓝桥杯列表交互题的最优解,也是必考点。
(1)核心优势
-
性能提升:无需循环给每个子元素绑定事件,减少内存占用
-
动态元素兼容:后续新增的子元素,自动拥有事件效果,无需重新绑定
-
代码更简洁:避免循环绑定的冗余代码
(2)结合示例代码的实现
原日期选择代码中,通过 for 循环给 7 个 item 分别绑定了 3 个事件,用事件委托优化后,只需给父元素.dataDiv绑定一次事件即可:
// 获取父元素
var dataDiv = document.querySelector('.dataDiv');
var lastIndex = 0;
var items = document.querySelectorAll('.item');
// 点击事件委托给父元素
dataDiv.addEventListener('click', function(e){
var target = e.target;
// 找到点击的item元素(兼容点击子div的情况)
var item = target.closest('.item');
if(!item) return; // 不是item元素,不执行
var index = item.getAttribute('index');
if(lastIndex == index) return;
// 高亮当前点击的item
item.id = 'bg';
item.style.color = 'red';
item.style.backgroundColor = 'rgb(215,215,214)';
// 清除上一个选中的样式
items[lastIndex].id = '';
items[lastIndex].style.color = 'black';
items[lastIndex].style.backgroundColor = '';
lastIndex = index;
});
// 鼠标移入事件委托(mouseenter不冒泡,需开启捕获阶段)
dataDiv.addEventListener('mouseenter', function(e){
var item = e.target.closest('.item');
if(!item) return;
var index = item.getAttribute('index');
console.log('mouseenter no.'+index+' div');
item.style.color = 'red';
item.style.backgroundColor = 'rgb(215,215,214)';
}, true);
// 鼠标移出事件委托
dataDiv.addEventListener('mouseleave', function(e){
var item = e.target.closest('.item');
if(!item) return;
var index = item.getAttribute('index');
console.log('mouseleave no.'+index+' div');
if(item.id == ''){
item.style.color = 'black';
item.style.backgroundColor = '';
}
}, true);
3. DOM 属性操作
(1)自定义属性
通过setAttribute()设置、getAttribute()获取自定义属性,常用于给元素存储额外数据。 代码示例:
// 给日期元素设置index属性,存储下标
item.setAttribute('index', i);
// 获取点击元素的index下标
var index = this.getAttribute('index');
(2)标准属性
直接通过元素对象修改 HTML 标准属性(如id、value、className等)。 代码示例:
// 切换div1的id属性
div1.id = div1.id == "dd" ? "dd2" : "dd";
4. 样式操作
(1)style属性
修改单个样式 ,CSS 属性名需转驼峰命名 (如font-size→fontSize)。 代码示例:
div2.style.color = "red";
div2.style.fontSize = "25px";
(2)className操作
通过修改class属性批量切换样式,追加类名时需注意空格分隔。 代码示例:
// 追加类名(注意前面的空格,避免和原有类名拼接)
div2.className += " div22";
(3)classList(推荐)
更灵活的类名操作,是蓝桥杯样式切换的首选方案,支持add()(添加)、remove()(移除)、contains()(判断是否存在)、toggle()(切换)。 代码示例:
div3.classList.add('div33'); // 添加类
if (div3.classList.contains('div333')) { // 判断类是否存在
div3.classList.remove('div333'); // 移除类
}
5. 类数组对象
querySelectorAll返回的NodeList是类数组对象 ,可通过for循环遍历,但不支持数组的push/filter等原生方法。 代码示例:
// 遍历所有item元素
for (var i = 0; i < items.length; i++) {
var item = items[i];
// 对每个item执行操作
}
二、DOM 核心知识点汇总表
基础 DOM 知识点汇总
|-------|--------------------|--------------------------------------------|-------------------------------------------------------|
| 知识点分类 | 具体内容 | 关键描述 | 代码示例 |
| 元素获取 | querySelector | 获取第一个匹配 CSS 选择器的元素 | document.querySelector('.text') |
| | querySelectorAll | 获取所有匹配元素的 NodeList 类数组 | document.querySelectorAll('.item') |
| 属性操作 | 自定义属性 | setAttribute()设置、getAttribute()获取自定义属性 | item.setAttribute('index', i) |
| | 标准属性 | 直接修改id/value/className等 HTML 标准属性 | div1.id = "dd2" |
| 样式操作 | style属性 | 修改单个样式,CSS 属性需转驼峰命名 | div2.style.color = "red" |
| | className | 覆盖或追加元素的 class 属性 | div2.className += " div22" |
| | classList | 灵活操作类名,支持 add/remove/contains/toggle,推荐使用 | div3.classList.add('div33') |
| 类数组对象 | NodeList 遍历 | 用 for 循环遍历 querySelectorAll 返回的类数组 | for (var i = 0; i < items.length; i++) { /* 操作 */ } |
事件系统专项汇总表
|--------|-----------------------------------|----------------------------------------|
| 知识点分类 | 具体内容 | 核心考点与适用场景 |
| 事件绑定方式 | HTML 行内绑定 | HTML 与 JS 耦合,仅适用于极简场景,蓝桥杯改错题型常考 |
| | DOM0 级绑定 | 写法简单,单事件单处理函数,tab 切换、简单点击场景首选 |
| | DOM2 级绑定 | 支持多处理函数、事件流控制,事件委托、复杂交互场景必考 |
| 事件对象 | event.target | 事件委托核心,获取实际触发事件的元素,必考 |
| | event.preventDefault() | 阻止元素默认行为,表单提交、a 标签场景必考 |
| | event.stopPropagation() | 阻止事件冒泡,解决父子元素事件冲突,高频考点 |
| 高频事件类型 | 表单事件(input/change/focus/blur) | 表单验证、实时输入处理,蓝桥杯表单题必考 |
| | 鼠标事件(click/mouseenter/mouseleave) | 点击交互、悬浮效果,基础交互题必考 |
| | 键盘事件(keydown/keyup) | 回车提交、快捷键、输入限制,高频考点 |
| 进阶机制 | 事件流(捕获 / 目标 / 冒泡) | 理解事件传播顺序,区分 mouseenter 与 mouseover 的核心 |
| | 事件委托 | 列表交互、动态元素的最优方案,蓝桥杯超高频必考 |
三、蓝桥杯 Web 应用开发赛道省赛备考建议
1. 核心考点优先级梳理
蓝桥杯 Web 省赛的考点有明确的权重分布,按优先级排序如下:
-
DOM 事件与交互(占比 40%+):事件绑定、事件委托、表单事件、鼠标事件是绝对核心,每年省赛至少 3 道题直接考察
-
DOM 样式与属性操作(占比 20%):classList、style 属性、自定义属性操作,是所有交互题的基础
-
本地存储 (占比 15%):
localStorage/sessionStorage的读写,todolist、数据持久化题必考 -
基础布局与 CSS(占比 15%):Flex 布局、定位、过渡动画,和 DOM 操作结合出题
-
JS 基础语法(占比 10%):数组方法、循环、条件判断,贯穿所有题目
2. 真题专项训练策略
-
事件专项突破 :集中刷「tab 切换」「表单验证」「列表点击高亮」「悬浮交互」四类题型,这四类题型 100% 覆盖事件核心考点,是省赛必出题。重点掌握事件委托的写法,省赛中动态渲染的列表题,必须用事件委托才能实现完整功能,也是评分的核心得分点。
-
限时模拟训练:严格按考试时间(4 小时)刷整套历年真题,提升做题速度与应试心态,避免出现 "会做但做不完" 的情况
-
错题复盘整理:重点分析错误原因,比如「oninput 和 onchange 用混」「事件委托的 target 判断错误」「this 指向混淆」,针对性强化薄弱点
3. 高频得分技巧与避坑指南
-
表单实时交互需求,优先用
oninput,不要用onchange,避免出现 "输入后不触发" 的问题 -
列表元素的事件绑定,优先用事件委托,不要循环绑定,既提升性能,也能兼容动态新增的元素
-
样式批量切换,优先用
classList操作类名,不要大量写style属性修改,代码更简洁,也更容易判分 -
代码写在
<head>中时,必须用window.onload或DOMContentLoaded包裹,避免出现 "获取不到 DOM 元素" 的低级错误 -
事件处理函数中,优先用
event.target获取触发元素,避免循环绑定中的闭包坑(比如示例中循环绑定的 i 值问题)