从零开始学前端 | 第十七章:事件机制与交互逻辑 本章定位上一章我们已经正式接触了 DOM。你已经学习了什么是 DOM。为什么页面会随着 JavaScript 改变。如何获取页面元素。如何修改文本、样式和页面结构。到这里你已经能做一些很有“页面感”的事情了。例如改标题文字改元素样式动态新增列表项但如果你继续往前走很快就会发现一个新的关键问题页面上的这些变化到底应该在什么时候发生比如为什么按钮要等用户点了之后才修改文字为什么输入框要等用户开始输入时才同步内容为什么表单会一提交就刷新页面为什么有些代码一加载页面就执行了而有些代码要等用户操作后才执行这些问题背后其实都指向同一个核心主题事件机制与交互逻辑这一章要解决的核心问题是用户的点击、输入、提交、键盘操作究竟是怎样触发 JavaScript 执行的。本章学习目标学完这一章后你应该能做到理解什么是事件以及为什么前端交互离不开事件。理解“页面加载时执行”和“事件触发后执行”的区别。认识常见事件点击、输入、提交、键盘事件。掌握最基础的事件监听写法。理解事件对象是什么以及它为什么有用。理解什么是默认行为知道为什么有时需要阻止默认行为。能完成按钮点击计数器、输入同步显示、阻止表单默认提交这类基础练习。一、为什么前端交互离不开事件前端页面和普通静态页面最大的区别之一就是它会响应用户操作。例如用户点击按钮用户输入文字用户按下键盘用户提交表单如果没有事件机制JavaScript 就很难知道用户到底做了什么动作以及应该在什么时机执行哪段代码。也就是说事件机制的核心价值是把“用户操作”和“代码执行”连接起来。二、什么是事件你可以先用一句最容易理解的话来记事件就是页面上发生的一件事。例如按钮被点击输入框内容发生变化表单被提交键盘被按下这些都可以看作事件。1. 事件不一定都来自用户点击很多纯小白第一次接触事件时会本能地把事件理解成“点击按钮”。点击当然很常见但事件远不止这一种。例如输入事件提交事件键盘事件页面加载相关事件所以更准确的理解应该是只要页面或用户操作中发生了一个值得被代码感知的动作它就可能被当作事件。2. 事件本质上是在告诉 JavaScript现在该你执行了你可以把事件想成一种“触发信号”。比如用户一点击按钮浏览器就知道“点击事件发生了”然后去执行你事先绑定好的那段代码这也是为什么交互逻辑通常不是页面一加载就全执行而是等某个事件真的发生时再执行对应逻辑。三、交互的本质用户操作触发代码执行这句话非常重要值得你从现在开始牢牢记住前端交互的本质通常就是用户操作触发代码执行。1. 一个最简单的交互理解例如你有一个按钮button点我一下/button如果只是有这个按钮但没有任何 JavaScript 去监听它那它被点击时往往不会发生你期待的页面逻辑变化。但如果你提前告诉浏览器这个按钮一被点击就执行某段代码。那交互就成立了。2. 为什么这一点必须先想清楚因为很多初学者一开始写交互时会混淆两件事页面加载时立即执行用户操作后才执行如果这两者不分清代码就很容易写乱。四、页面加载时执行和事件触发后执行有什么区别这是第十七章最关键的一层理解。1. 页面加载时执行例如scriptconsole.log(页面一加载这行代码就执行);/script这种代码不需要用户做任何事只要脚本执行到这里它就会立刻运行。2. 事件触发后执行例如button.onclickfunction(){console.log(只有点击按钮后这行代码才执行);};这段逻辑不会在页面一加载时立刻打印而是要等按钮真的被点了之后才运行。3. 一个非常实用的判断法你现在可以先这样区分1. 直接写在脚本顶层的代码通常更接近页面加载到这里就执行。2. 写在事件处理函数里的代码通常更接近事件发生时才执行。4. 为什么这层区别特别重要因为几乎所有交互逻辑都是建立在这层区别上的。例如页面初始化时准备数据用户点击后修改页面用户输入后同步提示用户提交后校验内容这些逻辑发生的时机并不一样。五、最常见的前端事件有哪些当前阶段最值得优先掌握的事件主要有四类点击事件输入事件提交事件键盘事件六、点击事件click点击事件是纯小白最容易理解的一种事件。它表示用户点击了某个元素。最常见场景例如点击按钮修改标题点击按钮计数点击按钮切换状态七、输入事件input输入事件通常表示用户正在输入框里输入内容输入值发生了变化。它特别适合这种场景输入什么就同步显示什么输入时实时判断长度输入时给出提示八、提交事件submit提交事件通常和表单有关。它表示用户触发了表单提交。例如点击表单里的提交按钮在某些输入框里按下回车很多初学者第一次写表单交互时就是在这里碰到“页面为什么刷新了”的问题。后面我们会专门讲这个点。九、键盘事件keydown键盘事件表示用户按下了某个键。例如按回车提交内容按某个键触发快捷操作当前阶段你不用一下子学得很深但先知道它的存在和基本用法非常有帮助。十、如何监听事件光知道事件存在还不够更关键的是我们怎么告诉浏览器某个事件发生时要执行哪段代码这件事通常就叫监听事件当前阶段最适合优先掌握的事件监听方式是addEventListener十一、addEventListener是什么你可以先把它理解成给某个元素添加一个事件监听器。它的基本意思就是当这个元素发生某种事件时执行我提供的函数。1. 基本写法元素.addEventListener(事件名,function(){事件发生时要执行的代码;});2. 一个最简单的按钮点击例子buttonidcount-button点我一下/buttonscriptconstcountButtondocument.getElementById(count-button);// 给按钮添加点击事件监听只有点击发生时才会执行里面的代码countButton.addEventListener(click,function(){console.log(按钮被点击了);});/script3. 为什么当前阶段更推荐先熟悉addEventListener因为它的语义更清楚给谁绑定事件监听什么事件事件发生后执行什么逻辑这三件事都写得比较直观。而且后面真实开发里它也非常常见。十二、事件处理函数是什么在事件监听里你经常会看到这样的结构button.addEventListener(click,function(){console.log(按钮被点击了);});这里的function(){console.log(按钮被点击了);}就可以先理解成事件发生后要执行的那段函数。你现在可以把它叫成事件处理函数事件回调函数当前阶段不必纠结术语先理解它在干什么最重要。1. 它和普通函数有什么关系本质上它还是函数。只是它不是你立刻主动调用而是等事件发生时由浏览器帮你调用。这个区别很重要。十三、一个完整示例按钮点击计数器下面我们来做一个非常经典的交互入门练习。目标是每点击一次按钮数字就加一。1. 示例代码p当前点击次数spanidcount-value0/span/pbuttonidcount-button点我加一/buttonscriptconstcountValuedocument.getElementById(count-value);constcountButtondocument.getElementById(count-button);letcount0;countButton.addEventListener(click,function(){// 每次点击按钮时先更新数据再把最新结果同步到页面count1;countValue.textContentcount;});/script2. 这段代码在做什么你可以按下面顺序理解1. 先找到页面上的数字显示区域constcountValuedocument.getElementById(count-value);2. 再找到按钮constcountButtondocument.getElementById(count-button);3. 准备一个变量保存当前点击次数letcount0;4. 当按钮被点击时更新数据并更新页面count1;countValue.textContentcount;3. 这个例子为什么很重要因为它第一次把下面这几件事完整串起来了获取元素监听点击事件更新变量更新 DOM这几乎就是很多交互的最基础模型。十四、输入事件让输入框内容实时同步显示点击事件是最基础的一类交互而输入事件则会让你开始理解页面可以随着用户输入实时变化。1. 示例代码inputidname-inputtypetextplaceholder请输入你的名字/p你好spanidpreview-name前端学习者/span/pscriptconstnameInputdocument.getElementById(name-input);constpreviewNamedocument.getElementById(preview-name);nameInput.addEventListener(input,function(){// 输入框内容变化时实时把最新值同步到预览区域previewName.textContentnameInput.value||前端学习者;});/script2. 这里新增了什么知识点这个例子除了事件监听还让你第一次接触到了input.value你可以先把它理解成输入框当前的值。3. 为什么这个例子很有代表性因为真实页面里很多交互本质上都在做类似事情用户输入代码拿到输入值页面根据这个值及时更新这类逻辑在表单、搜索框、消息输入区里都很常见。十五、表单默认行为是什么表单是前端里一个非常重要的交互场景。但很多纯小白第一次写表单时会遇到一个很困惑的问题为什么我一点击提交页面就刷新了这通常不是代码坏了而是因为表单本身有默认行为。1. 什么叫默认行为你可以先这样理解默认行为就是浏览器在某些事件发生时本来就会自动做的事情。例如表单提交时浏览器通常会尝试提交并刷新页面。2. 为什么这会影响前端交互因为有时候你并不想让浏览器立刻按默认方式处理。比如你可能想先做前端校验提示用户哪里没填确认数据格式是否正确这时如果页面一提交就刷新你自己的提示逻辑可能就来不及展示了。所以你需要学会在合适的时候阻止默认行为。十六、事件对象是什么当事件发生时浏览器通常不只是“通知你一下”它还会把一些和这次事件相关的信息交给你。这份信息通常就通过一个参数传进事件处理函数里。这个参数通常被叫做事件对象1. 一个最基础的写法form.addEventListener(submit,function(event){console.log(event);});这里的event就是事件对象。2. 当前阶段怎么理解事件对象你现在不用急着把它理解得特别深。先记住一句话就很好事件对象里装着“这次事件相关的信息和操作能力”。例如这次是什么事件是哪个元素触发的能不能阻止默认行为3. 当前阶段最常用到的一个能力preventDefault在表单学习里你最先高频用到的就是event.preventDefault()它的作用可以先理解成阻止浏览器这次事件的默认行为。十七、一个完整示例阻止表单默认提交改为前端校验提示下面我们做一个非常典型的实战入门例子。目标是用户提交表单时先不要刷新页面先由前端检查输入内容再给出提示1. 示例代码formidsignup-forminputiduser-name-inputtypetextplaceholder请输入用户名/buttontypesubmit提交/button/formpidform-message/pscriptconstsignupFormdocument.getElementById(signup-form);constuserNameInputdocument.getElementById(user-name-input);constformMessagedocument.getElementById(form-message);signupForm.addEventListener(submit,function(event){// 先阻止表单默认提交避免页面立刻刷新event.preventDefault();constuserNameuserNameInput.value.trim();if(userName){formMessage.textContent用户名不能为空请先输入内容;formMessage.style.color#f56c6c;return;}formMessage.textContent提交成功欢迎你${userName};formMessage.style.color#67c23a;});/script2. 这个例子在练什么它已经同时串起了很多本章核心内容获取表单和输入框元素监听submit事件使用事件对象阻止默认行为读取输入框的值做简单前端校验把结果显示到页面上3. 为什么这里要先preventDefault因为如果不阻止默认行为浏览器可能会先按表单提交的默认流程处理页面就容易刷新。一刷新你刚刚想显示的提示内容可能就看不到了。所以这一句event.preventDefault();在这种场景里非常关键。4. 为什么这里用了return这一点也很值得初学者注意。当用户名为空时我们已经给出了错误提示formMessage.textContent用户名不能为空请先输入内容;这时候就不应该继续往下执行“提交成功”的逻辑了。所以这里用return;来提前结束当前这次处理流程。这也和你前面学过的“避免不必要的深层嵌套”是连起来的。十八、键盘事件一个最基础的认识当前阶段键盘事件你先建立基础直觉就够了。例如inputidkeyword-inputtypetextplaceholder按下键盘试试看/scriptconstkeywordInputdocument.getElementById(keyword-input);keywordInput.addEventListener(keydown,function(){console.log(用户按下了一个键);});/script这说明当用户在输入框里按下键盘时也可以触发事件。后面如果你继续学习更深入的交互逻辑会经常接触回车确认快捷键键盘控制所以当前阶段先知道有这类事件并能做最基础监听就很好。十九、为什么很多交互都能拆成同一个模式走到这里你会发现很多交互虽然表面看起来不一样但本质上经常都能拆成同一个流程找到元素监听事件事件发生读取当前数据更新页面或更新状态例如点击计数器是这样输入同步显示是这样表单校验也是这样这会是你后面学习更复杂前端开发时非常重要的一层思维。也就是说交互逻辑往往不是“随便写几行效果代码”而是有稳定结构的。二十、事件机制和前面学过的知识是怎么连起来的这一章不是完全新的孤岛而是在把前面学过的 JavaScript 和 DOM 真正接到“用户操作”上。1. 变量会继续使用例如点击次数、输入值、校验结果都需要变量来保存。2. 条件判断会继续使用例如输入是否为空是否通过校验是否切换高亮状态3. 函数会继续出现事件处理逻辑本质上还是函数只是它由事件触发。4. DOM 操作会继续出现事件发生后很多时候最终仍然要回到改文本改样式新增内容所以你可以把这一章理解成DOM 告诉你“能改页面”事件机制告诉你“什么时候改页面”。二十一、初学者最容易踩的坑这一章的坑非常典型而且很多人会在这里第一次真正体会到“代码时机”这个问题。1. 把“绑定事件”和“立刻执行”混为一谈事件监听不是让代码立刻执行而是先把规则绑定好等事件发生时再执行。这一点一定要反复体会。2. 还没分清页面加载执行和事件触发执行如果这一层没想清楚写交互时就很容易疑惑为什么这行代码一开始就跑了为什么那行代码点击后才跑所以每写一段交互代码时都可以先问自己这段代码是页面一加载就执行还是等用户操作后才执行3. 忘记阻止表单默认行为这会直接导致页面刷新提示信息看不到调试过程很混乱所以一旦你是在做“前端先校验再提示”的表单交互就要想到event.preventDefault();4. 输入事件里没有正确读取输入框值输入框最常见的值来源是input.value如果没拿对值页面同步逻辑就会看起来不对。5. 事件写对了但修改的 DOM 元素不对有时问题不是事件没触发而是找错元素了改错元素了改了一个用户根本看不到的地方所以交互调试时不要只盯着事件也要看事件触发后真正被改的是不是你想改的那个元素。6. 一上来就做复杂联动当前阶段更推荐你先把下面几类小交互练熟点击后改文本输入后同步显示提交前做基础校验这三类练熟后再做更复杂的联动会稳很多。二十二、本章实践练习这一章最适合做“操作一发生页面就有反馈”的交互练习。重点不是页面有多复杂而是让你真正体会事件就是用户操作和 JavaScript 执行之间的连接点。1. 练习 1实现按钮点击计数器请创建一个显示数字的区域一个按钮每点击一次按钮就让数字加一。这个练习重点是监听点击事件用变量保存状态用 DOM 同步页面2. 练习 2监听输入框内容变化并同步显示请创建一个输入框一个文字预览区域用户输入什么预览区就同步显示什么。这个练习重点是监听input事件使用input.value把值写回页面3. 练习 3阻止表单默认提交改为前端校验提示请创建一个表单一个输入框一个提交按钮一个提示区域当输入为空时阻止提交并提示“请输入内容”。当输入不为空时提示“提交成功”。这个练习重点是监听submit使用事件对象调用preventDefault做简单条件判断4. 挑战练习监听键盘输入如果你想再多练一点可以试试下面这个小挑战当用户在输入框里按下键盘时在页面上显示你刚刚按下了一个键这个练习重点是先建立对键盘事件的基础感觉不要求你一开始就做复杂快捷键逻辑。二十三、学习重点提示这一章最重要的不是一下子记住很多事件名而是先真正建立“触发时机”的思维。请重点记住事件就是页面上发生的一件事。前端交互的本质通常是“用户操作触发代码执行”。一定要分清“页面加载时执行”和“事件触发后执行”。addEventListener是当前阶段最重要的事件监听方式。点击、输入、提交、键盘事件是最值得优先掌握的四类常见事件。事件对象里装着这次事件相关的信息和操作能力。表单交互里经常需要用preventDefault阻止默认行为。交互逻辑通常可以拆成找元素 - 监听事件 - 事件发生 - 更新状态或页面。如果你只记一句话请记住事件机制解决的核心问题不是“页面能不能改”而是“页面应该在什么时候因为哪种操作而改变”。二十四、本章小结这一章你已经从“JavaScript 能改页面”进一步走到了“JavaScript 会在用户操作后改页面”。你已经学习了什么是事件为什么前端交互离不开事件页面加载执行和事件触发执行的区别点击、输入、提交、键盘事件的基础认识如何使用addEventListener监听事件什么是事件对象什么是默认行为以及为什么要阻止默认行为如何完成点击计数、输入同步、表单校验这类基础交互这一步非常关键。因为从这一章开始你对前端页面的理解已经不再只是“静态内容 DOM 修改”而是开始真正具备用户一操作页面就有对应反馈的交互思维。后面当你学习定时器、异步请求、组件开发时这种“触发 - 处理 - 更新”的思路会一直陪着你。二十五、课后思考题请你思考下面几个问题为什么说事件可以理解成“页面上发生的一件事”为什么“页面加载时执行”和“事件触发后执行”必须分清为什么说交互的本质通常是“用户操作触发代码执行”事件对象最先让你感受到的实际价值是什么为什么表单交互里经常需要阻止默认行为为什么很多交互都能拆成“找元素 - 监听 - 更新页面”这套流程建议你用自己的话把答案写下来。只要你能把这些问题说明白说明你已经真正开始建立前端交互逻辑的思维了。二十六、下一章预告下一章我们会继续学习从零开始学前端 | 第十八章定时器、异步与网络请求初步到那时你会开始接触“不是所有代码都会立刻按顺序执行完”的问题也会第一次真正碰到从外部接口获取数据再展示到页面上的流程。

本月热点