JavaScript 事件与事件监听学习笔记
一、这一章在讲什么
这一章主要讲网页中的“事件”和“事件监听”。
事件就是用户或浏览器在页面上发生的动作,比如点击、鼠标移入、键盘按下、输入内容、提交表单。事件监听就是提前告诉浏览器:某个元素一旦发生某种事件,就执行指定函数。除此之外,这一章还顺带讲了常见事件类型、批量给多个元素绑定事件、document/ DOM /querySelector的关系,以及简单的 JS 模块化写法。
二、核心概念
1. 事件
- 它是什么
- 事件就是发生在 HTML 元素上的事情。
- 例如:
click点击、mouseenter鼠标移入、keydown键盘按下。
- 有什么作用
- 没有事件,页面就是静态的。
- 有了事件,页面才能和用户互动。
- 它的原理
- 浏览器会监听用户操作和页面状态变化。
- 一旦对应动作发生,就会触发相应事件。
- 初学者容易混淆的点
- 事件是“事情本身”,不是代码。
- 比如“按钮被点击”是事件,不是事件监听。
2. 事件监听
- 它是什么
- 事件监听就是给元素注册一个响应规则:某事件发生时,执行某个函数。
- 也叫事件绑定、注册事件。
- 有什么作用
- 让页面在用户操作时做出反应,比如弹窗、改颜色、改内容。
- 它的原理
- JS 先把处理函数交给浏览器保存。
- 等事件真的发生时,浏览器再调用这个函数。
- 初学者容易混淆的点
- 监听不是“立刻执行函数”,而是“先登记,等触发再执行”。
3. 事件三要素
- 它是什么
- 事件源、事件类型、事件触发后执行的函数。
- 有什么作用
- 帮助我们完整理解一段事件代码到底在干什么。
- 它的原理
事件源.addEventListener('事件类型', 处理函数)
- 初学者容易混淆的点
- 事件源是“谁触发”,事件类型是“发生什么事”,函数是“怎么处理”。
4.document
- 它是什么
document是浏览器提供的对象,代表当前整个网页文档。
- 有什么作用
- 它是 JS 操作页面的常用入口。
- 它的原理
- 浏览器解析 HTML 后,会生成 DOM 结构,
document可以访问这套结构。
- 浏览器解析 HTML 后,会生成 DOM 结构,
- 初学者容易混淆的点
document不是 HTML 标签,也不是整个 DOM 本身,而是进入页面结构的入口对象。
5. DOM
- 它是什么
- DOM 是文档对象模型,可以理解成“浏览器眼中的网页结构”。
- 有什么作用
- 把 HTML 页面变成 JS 能操作的一组对象。
- 它的原理
- 浏览器把 HTML 解析成一棵 DOM 树,每个标签都会变成对象节点。
- 初学者容易混淆的点
- HTML 是源码,DOM 是浏览器解析后的对象结构,它们有关联,但不是同一个东西。
6.querySelector/querySelectorAll
- 它是什么
- 它们是查找 DOM 元素的方法。
- 有什么作用
- JS 想操作页面,必须先找到元素。
- 它的原理
- 按 CSS 选择器规则在 DOM 中查找目标元素。
querySelector()返回第一个匹配元素。querySelectorAll()返回所有匹配元素组成的集合。
- 初学者容易混淆的点
querySelector找一个。querySelectorAll找一组,不是单个元素,通常要配合循环使用。
7.this(在本章代码里的基本含义)
- 它是什么
- 在普通函数写法的事件处理中,
this常表示当前触发事件的那个元素。
- 在普通函数写法的事件处理中,
- 有什么作用
- 可以直接操作“当前被触发”的元素。
- 它的原理
- 浏览器在调用事件处理函数时,会把当前元素作为调用对象。
- 初学者容易混淆的点
- 本章里的
this不是“所有元素”,而是“当前触发事件的那个元素”。 - 比如鼠标移入第 3 个
tr,this指的就是第 3 个tr。
- 本章里的
8. 模块化(export/import)
- 它是什么
- 把功能拆到不同 JS 文件中,再互相导入导出。
- 有什么作用
- 代码更清楚,更方便复用和维护。
- 它的原理
- 一个文件用
export导出功能,另一个文件用import引入功能。 - 在 HTML 中通常要写
type="module"。
- 一个文件用
- 初学者容易混淆的点
src是引入文件路径,type="module"是告诉浏览器:这个脚本按模块方式处理。
三、重难点
1. 事件和事件监听不是一回事
- 结论
- 事件是动作本身,事件监听是对这个动作做出响应的机制。
- 原因
- 事件是“发生了什么”,监听是“发生后怎么办”。
- 通俗比喻
- 门铃响了,这是事件;你听到门铃去开门,这是事件监听后的处理。
2. 为什么要先querySelector
- 结论
- JS 不能凭空操作页面,必须先找到目标元素。
- 原因
- 事件、样式修改、内容修改,都得先明确“操作谁”。
- 通俗比喻
- 先找到人,才能通知他做事;先找到元素,JS 才能控制它。
3.querySelectorAll('tr')后为什么要用for
- 结论
- 因为拿到的是一组
tr,不是单个tr。
- 因为拿到的是一组
- 原因
- 事件监听是给具体元素绑定的,不能把一整组元素直接当一个元素来绑定。
- 通俗比喻
- 你拿到的是全班名单,不是某一个同学。要给每个人发通知,就得一个一个发。
4.this指向谁
- 结论
- 在本章这种普通函数写法里,
this指当前触发事件的元素。
- 在本章这种普通函数写法里,
- 原因
- 事件函数是由当前元素触发并调用的。
- 通俗比喻
- 谁“出事”了,
this通常就是谁。
- 谁“出事”了,
5.onclick和addEventListener的区别
- 结论
- 更推荐
addEventListener。
- 更推荐
- 原因
onclick容易被后面的赋值覆盖;addEventListener可以给同一个元素绑定多个同类事件处理函数,扩展性更强。
- 小例子
onclick像黑板上只留一个值,后写的会把前写的擦掉。addEventListener像便签墙,可以贴多张便签。
6. 常见事件容易混
- 结论
- 事件名不同,触发时机就不同。
- 原因
- 浏览器会根据事件类型决定什么时候执行函数。
- 小例子
focus是“开始选中输入框”,input是“真的开始输入内容”,blur是“离开输入框”。
7. JS 操作页面的流程要串起来理解
- 结论
- 浏览器先解析 HTML,生成 DOM;JS 再通过
document和querySelector找元素;最后绑定事件并修改页面。
- 浏览器先解析 HTML,生成 DOM;JS 再通过
- 原因
- JS 操作的不是 HTML 文本,而是 DOM 对象。
- 通俗比喻
- HTML 像图纸,DOM 像建好的房间,JS 是拿着钥匙进去操作的人。
四、代码理解
1. 最基础的事件监听
constbtn=document.querySelector('#btn');// 1. 找到按钮btn.addEventListener('click',function(){// 2. 绑定点击事件alert('hello');// 3. 点击后执行});关键理解
document:当前网页文档入口querySelector('#btn'):找到 id 为btn的元素addEventListener('click', ...):监听点击事件function () { ... }:点击后执行的函数
语法规则总结
事件源.addEventListener('事件类型',处理函数);- 事件类型要写成字符串,比如
'click' - 在
addEventListener里写的是'click',不是'onclick'
2. 批量给表格行绑定事件
consttrs=document.querySelectorAll('tr');// 1. 获取所有 trfor(leti=0;i<trs.length;i++){// 2. 遍历每个 trtrs[i].addEventListener('mouseenter',function(){// 3. 鼠标移入this.style.backgroundColor='#f2e2e2';// 4. 当前行变色});trs[i].addEventListener('mouseleave',function(){// 5. 鼠标移出this.style.backgroundColor='#fff';// 6. 恢复颜色});}每一步在做什么
- 拿到所有表格行。
- 用循环一个个处理。
- 给每一行绑定鼠标移入事件。
- 移入时把当前行背景色改掉。
- 给每一行绑定鼠标移出事件。
- 移出时恢复背景色。
这里的关键点
querySelectorAll()返回的是集合。for循环是为了给每一个元素分别绑定事件。this表示当前被鼠标移入或移出的那一行。- JS 中写样式是
backgroundColor,不是background-color。
3. 常见事件速记
click// 点击mouseenter// 鼠标移入mouseleave// 鼠标移出keydown// 键盘按下keyup// 键盘抬起focus// 获得焦点blur// 失去焦点input// 输入内容时submit// 表单提交时4. 模块化的最小示例
<scriptsrc="./js/eventDemo.js"type="module"></script>// utils.jsexportfunctionprintLog(msg){console.log(msg);}// eventDemo.jsimport{printLog}from'./utils.js';document.querySelector('#btn').addEventListener('click',function(){printLog('按钮被点击了');});理解
export:把功能导出去import:把别的文件里的功能拿进来type="module":告诉浏览器,这个脚本使用模块化语法
五、易错点
- 把事件和事件监听混为一谈。
- 事件是动作,监听是处理机制。
- 在
addEventListener里把事件名写成onclick。
- 正确写法是
'click'。
- 以为
querySelectorAll()拿到的是一个元素。
- 它返回的是一组元素,通常要用循环。
- 把
this理解成“所有元素”或“整个数组”。
- 本章这里的
this指当前触发事件的那个元素。
- 在 JS 中写 CSS 属性时还写成
background-color。
- JS 里要写
backgroundColor。
- 分不清
focus、input、blur。
focus:点进去input:内容变化blur:离开
- 分不清
document、DOM、querySelector。
document是入口- DOM 是页面对象结构
querySelector是查找元素的方法
六、记忆口诀 / 通俗比喻
- 事件是动作,监听是等动作发生后再处理。
- 先找元素,再谈操作。
**querySelector找一个,querySelectorAll找一窝。**- 谁触发事件,
this常常就是谁。 - HTML 是图纸,DOM 是成品房,JS 是操作员。
**onclick易覆盖,addEventListener更能打。****focus进,input写,blur走。**
七、应用
下面用一个完整的小案例,把这章的知识串起来。
场景:做一个“学生信息表”交互页面
需求:
- 鼠标移入表格行时,高亮当前行
- 鼠标移出时,恢复原色
- 输入框获得焦点时,边框变色
- 输入内容时,实时显示当前输入了什么
- 点击按钮时,输出提示信息
- 使用模块化把“打印日志”单独拆出去
这个例子里,几乎把本章的主线都串起来了:
- 先有 HTML 页面结构
- 浏览器把 HTML 解析成 DOM
- JS 通过
document和querySelector/querySelectorAll找到元素 - 再通过
addEventListener绑定不同事件 - 最后在事件触发时修改样式或输出内容
完整代码
<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>事件监听案例</title><style>body{font-family:Arial,sans-serif;padding:20px;}table{border-collapse:collapse;width:400px;margin-top:20px;}th, td{border:1px solid #ccc;padding:10px;text-align:center;}#username{padding:8px;outline:none;border:1px solid #ccc;}#preview{margin-top:10px;color:#666;}</style></head><body><h2>学生信息交互演示</h2><inputid="username"type="text"placeholder="请输入姓名"><buttonid="btn">提交</button><divid="preview">当前输入:无</div><table><tr><th>姓名</th><th>年龄</th></tr><tr><td>张三</td><td>18</td></tr><tr><td>李四</td><td>19</td></tr><tr><td>王五</td><td>20</td></tr></table><scriptsrc="./js/eventDemo.js"type="module"></script></body></html>// utils.jsexportfunctionprintLog(msg){console.log(msg);}// eventDemo.jsimport{printLog}from'./utils.js';constbtn=document.querySelector('#btn');constinput=document.querySelector('#username');constpreview=document.querySelector('#preview');consttrs=document.querySelectorAll('tr');btn.addEventListener('click',function(){printLog('按钮被点击了');});input.addEventListener('focus',function(){this.style.borderColor='skyblue';});input.addEventListener('blur',function(){this.style.borderColor='#ccc';});input.addEventListener('input',function(){preview.innerText='当前输入:'+this.value;});for(leti=1;i<trs.length;i++){trs[i].addEventListener('mouseenter',function(){this.style.backgroundColor='#f2e2e2';});trs[i].addEventListener('mouseleave',function(){this.style.backgroundColor='#fff';});}按逻辑顺序串讲一遍
1. 先有 HTML 结构
页面里有:
- 一个输入框
- 一个按钮
- 一个提示文字区域
- 一张表格
这时它们只是 HTML 标签,是页面的原始结构。
2. 浏览器解析 HTML,生成 DOM
浏览器加载页面后,会把这些标签解析成 DOM 对象。
这时候输入框、按钮、表格行都不再只是“文本标签”,而是 JS 可以操作的对象。
所以后面 JS 才能写:
document.querySelector('#btn')document.querySelector('#username')document.querySelectorAll('tr')
3.document是入口,querySelector是查找工具
constbtn=document.querySelector('#btn');constinput=document.querySelector('#username');constpreview=document.querySelector('#preview');consttrs=document.querySelectorAll('tr');这一步的本质是:先找到元素,再谈操作。
document:当前网页文档入口querySelector():找第一个匹配元素querySelectorAll():找所有匹配元素
这里的trs是一个表格行集合,不是单个元素,所以后面要配合循环使用。
4. 给按钮绑定点击事件
btn.addEventListener('click',function(){printLog('按钮被点击了');});这里的三要素很完整:
- 事件源:
btn - 事件类型:
click - 处理函数:点击后调用
printLog
这说明事件监听的基本格式就是:
事件源.addEventListener('事件类型',处理函数);5. 给输入框绑定焦点和输入事件
input.addEventListener('focus',function(){this.style.borderColor='skyblue';});input.addEventListener('blur',function(){this.style.borderColor='#ccc';});input.addEventListener('input',function(){preview.innerText='当前输入:'+this.value;});这部分把三个常见事件区分得很清楚:
focus:点进输入框时触发blur:离开输入框时触发input:输入内容变化时触发
这里的this指当前触发事件的输入框本身,所以可以直接写:
this.style.borderColorthis.value
6. 给多个tr批量绑定事件
for(leti=1;i<trs.length;i++){trs[i].addEventListener('mouseenter',function(){this.style.backgroundColor='#f2e2e2';});trs[i].addEventListener('mouseleave',function(){this.style.backgroundColor='#fff';});}这一步是本章很关键的地方。
因为:
querySelectorAll('tr')拿到的是所有表格行- 它返回的是一组元素
- 所以不能直接对整组元素写
addEventListener - 必须通过
for循环,一个一个绑定
这里i = 1开始,是为了跳过表头那一行,只给数据行加效果。
当鼠标移入某一行时:
this.style.backgroundColor='#f2e2e2';说明当前行背景色变了。
鼠标移出时再恢复为白色。
7. 模块化在这个例子里怎么体现
import{printLog}from'./utils.js';exportfunctionprintLog(msg){console.log(msg);}说明:
utils.js负责提供工具函数eventDemo.js负责页面交互逻辑- 功能拆开后,代码更清楚
HTML 中写:
<scriptsrc="./js/eventDemo.js"type="module"></script>是因为这里使用了import/export,所以要告诉浏览器:这个脚本按模块方式运行。
这个案例把本章主线怎么串起来
可以把整个流程压缩成下面这条主线:
- HTML 提供页面结构:输入框、按钮、表格。
- 浏览器解析成 DOM:页面元素变成 JS 可操作对象。
- JS 通过
document找元素:用querySelector/querySelectorAll定位目标。 - 给元素绑定事件:点击、移入、移出、获得焦点、失去焦点、输入。
- 事件触发时执行函数:修改样式、改文字、输出日志。
- 模块化优化代码:把工具函数拆出去,提高可维护性。
所以网页能“动起来”,本质就是:
先找到 DOM 元素,再监听事件,最后在事件触发时操作元素。
这就是本章最核心的实际应用逻辑。
八、最终总结
这一章的核心,是理解“页面为什么能动起来”。事件是用户操作,事件监听是浏览器在事件发生时执行对应函数。JS 想操作页面,必须先通过document和querySelector找到 DOM 元素。addEventListener是更推荐的事件绑定方式,常配合循环给多个元素批量绑定事件。模块化部分先记住结论:代码可以拆文件,export导出,import导入,模块脚本通常写type="module"。