news 2026/10/5 10:22:58

MDN Learning Area 事件(Events)专项练习评分指南与参考实现解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MDN Learning Area 事件(Events)专项练习评分指南与参考实现解析
  • 教程
  • 示例工程

【免费下载链接】learning-area

GitHub repo for the MDN Learning Area.

项目地址:https://gitcode.com/gh_mirrors/le/learning-area
点击查看免费下载

导读

本指南围绕 MDN Learning Area 中「JavaScript 构建模块 · 事件(Events)」一章的配套练习展开,对应仓库文件为 marking.md。该练习通过三个由浅入深的任务,检验学习者对addEventListener()、键盘事件对象KeyboardEvent.key、事件冒泡(bubbling)与e.target的掌握程度。读完本文,你将得到每道任务的完整参考代码、逐行原理说明、可交互的在线练习入口,以及一套可复用的自评与调试方法,可直接对照本仓库中的起始代码进行练习与自查。

一、任务体系概览:三种练习形态

本仓库在 events 目录下为每个任务提供了两种文件形态:

文件用途
eventsN.html(如 events1.html)可交互练习版:页面内置<textarea class="playable playable-js">代码编辑区与 Reset 按钮,输入代码实时执行
eventsN-download.html(如 events1-download.html)可下载的独立 HTML 版本,适合在浏览器中直接打开调试,错误会输出到浏览器 JavaScript 控制台

可交互版本的运行机制由同目录下的 playable.js 实现:页面加载时调用fillCode(),将编辑区中的代码通过eval()执行;用户每次输入都会触发input事件重新执行;若代码抛错,错误信息会被捕获并渲染到结果面板(section)中,帮助你定位问题。点击 Reset 按钮则恢复初始代码(playable.js)。页面的预览区与编辑区样式由 styles.css 统一定制。

也就是说:在页面上做练习时,如果代码有误,错误信息会直接显示在结果面板上;使用-download.html版本时,请打开浏览器开发者工具的 Console 查看报错。

二、Task 1:用addEventListener实现按钮状态切换

2.1 题目要求

为页面中的按钮创建一个简单的事件处理器:点击一次切换按钮文字,再点击一次切换回来。要求只修改 JavaScript,不改动 HTML。起始 HTML 结构(见 events1-download.html):

<button class="off">Machine is off</button>

起始脚本:

const btn = document.querySelector('.off'); // Add your code here

2.2 参考实现

const btn = document.querySelector("button"); btn.addEventListener("click", () => { if (btn.className === "on") { btn.textContent = "Machine is off"; btn.className = "off"; } else { btn.textContent = "Machine is on"; btn.className = "on"; } });

2.3 逐行原理

  • document.querySelector("button"):选中页面中唯一的按钮元素,也可以沿用起始代码的document.querySelector('.off'),两者等价;
  • btn.addEventListener("click", () => { ... }):为按钮挂载点击事件监听器。注意这里传入的是箭头函数形式的回调函数,而不是调用结果,因此函数体不会在注册时立即执行;
  • 状态判断:通过btn.className判断当前按钮处于"on"还是"off"状态。初始 class 为"off",因此首次点击进入else分支,将文字改为"Machine is on"、class 改为"on";再次点击则走if分支,恢复"Machine is off"/"off"。

评分要点:该任务的核心是理解「事件监听器是函数的注册」以及「利用已有 DOM 属性维护状态」,参考实现中 class 切换同时服务于样式与状态判断,这是常见且简洁的做法。

三、Task 2:用键盘事件与KeyboardEvent.key驱动 Canvas 圆形移动

3.1 题目要求

为给定的 canvas 构建事件处理器,当按下 WASD 键时让圆形在画布内移动。圆形由预置函数drawCircle()绘制。起始代码(见 events2-download.html):

<canvas width="480" height="320" tabindex="0"></canvas>
const canvas = document.querySelector('canvas'); const ctx = canvas.getContext('2d'); function drawCircle(x, y, size) { ctx.fillStyle = 'white'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.beginPath(); ctx.fillStyle = 'black'; ctx.arc(x, y, size, 0, 2 * Math.PI); ctx.fill(); } let x = 50; let y = 50; const size = 30; drawCircle(x, y, size); // Add your code here

3.2 参考实现

window.addEventListener("keydown", (e) => { switch (e.key) { case "a": x -= 2; break; case "d": x += 2; break; case "w": y -= 2; break; case "s": y += 2; break; } drawCircle(x, y, size); });

3.3 逐行原理

  • window.addEventListener("keydown", ...):键盘事件监听器挂在window上,确保无论焦点在页面哪个位置都能捕获按键;
  • e.key:事件对象KeyboardEvent的key属性返回按键的字符值——小写"a"、"d"、"w"、"s"。这是现代浏览器推荐的判断方式(相较已废弃的keyCode更直观、跨平台一致);
  • switch分支:a让 x 坐标减 2(向左)、d让 x 加 2(向右)、w让 y 减 2(向上)、s让 y 加 2(向下);每个分支后的break必不可少,否则会发生 case 穿透(fall-through),导致一次按键同时执行多个位移;
  • 位移后调用drawCircle(x, y, size)重绘。drawCircle内部先用白色fillRect清空整块画布,再以黑色arc + fill在新坐标绘制圆形,形成「移动 + 重绘」的经典 Canvas 动画模式。

评分要点:该任务考察键盘事件与事件对象的使用,以及状态变量(x/y)在事件回调间共享的能力。canvas上设置了tabindex="0",说明画布本身也可聚焦,键盘事件处理因此对可访问性同样友好。

四、Task 3:借助事件冒泡与e.target实现按钮组统一监听

4.1 题目要求

在按钮组的父元素上设置点击监听器:点击任意按钮时,利用e.target读取被点击按钮的data-color属性,并将.button-bar的背景色设为该颜色。要求不遍历所有按钮、不给每个按钮单独挂监听器,以此考查对事件冒泡(事件委托)的理解。起始结构(见 events3-download.html):

<div class="button-bar"> <button>const buttonBar = document.querySelector(".button-bar"); function setColor(e) { buttonBar.style.backgroundColor = e.target.getAttribute("data-color"); } buttonBar.addEventListener("click", setColor);

4.3 逐行原理

  • buttonBar.addEventListener("click", setColor):监听器只挂在父容器.button-bar上。由于点击事件会从目标元素**向上冒泡(bubble)**到祖先元素,因此任意按钮的点击最终都会被父容器捕获,无需为 4 个按钮逐一注册监听器;
  • e.target:事件对象上的target属性指向真正被点击的元素(即具体的某个<button>),而不是监听器所在的父容器,这是事件委托得以成立的关键;
  • e.target.getAttribute("data-color"):通过getAttribute读取按钮上的自定义数据属性data-color的值("red"、"yellow"、"green"、"purple"),再赋给buttonBar.style.backgroundColor,完成背景色切换。

评分要点:这里尤其值得注意e.target与e.currentTarget的区别——前者是被点击的实际目标,后者是挂载监听器的元素。若误用e.currentTarget(即buttonBar),将因父容器没有data-color属性而取到null,背景色不会变化。这一陷阱正是该任务考察的核心知识点。

五、评估与调试:错误定位与自测清单

根据 marking.md 的说明,练习环境内置了错误反馈机制:

  1. 交互版(eventsN.html):代码出错时,异常会被fillCode()捕获并渲染到结果面板(<section class="preview">),无需打开控制台即可看到错误信息;
  2. 下载版(eventsN-download.html):错误输出到浏览器 JavaScript 控制台,请按 F12 打开开发者工具查看;
  3. Reset 按钮:任何时刻点击 Reset 即可将编辑区恢复为起始代码,便于反复重做。

自测清单可对照以下几点逐条验收:

  • Task 1:初始文字为 "Machine is off",点击后变为 "Machine is on",再次点击恢复;按钮 class 在on/off间往返切换;
  • Task 2:按下a/d/w/s时圆形分别向左/右/上/下移动,且每次按键画布先被清空再重绘,无残影;一次按键只触发一个方向移动(验证break没有遗漏);
  • Task 3:分别点击四个按钮,背景色依次变为红、黄、绿、紫;整个实现只有一处addEventListener(验证未给每个按钮单独绑定)。

六、结语

三个任务共同勾勒出 JavaScript 事件处理的完整能力图谱:addEventListener的正确注册(Task 1)、事件对象e.key的读取与状态驱动(Task 2)、事件冒泡与e.target的事件委托(Task 3)。结合本仓库的 可交互练习页(及 Task 2、Task 3)边改边跑,再对照 marking.md 的参考实现逐行比对,即可完成一次闭环的自我评估。如需扩展练习,还可以基于 events 目录下的起始文件,尝试为 Task 2 增加边界判断(防止圆形移出画布),或为 Task 3 增加事件委托之外的更多自定义属性读取逻辑。

  • 教程
  • 示例工程

【免费下载链接】learning-area

GitHub repo for the MDN Learning Area.

项目地址:https://gitcode.com/gh_mirrors/le/learning-area
点击查看免费下载
上一篇:Presto 0.225 版本技术解析:查询任务管控、GCS 认证、JDBC 大小写匹配与 SPI 演进
下一篇:Apache Pulsar C++ 客户端实战指南:编译安装、消息生产消费与 TLS 认证

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 10:21:56

MiniMax H3 实测:8GB显存跑2K视频+原生音频,开源视频生成的新卷王

MiniMax H3 实测&#xff1a;8GB显存跑2K视频原生音频&#xff0c;开源视频生成的新卷王 本文由 赛博仓鼠 整理撰写&#xff0c;持续追踪 AI 前沿动态与工具实测。网盘资源长期更新&#xff0c;文末自取。 一、MiniMax H3 是什么&#xff1f;为什么它能掀起开源视频生成的新浪潮…

作者头像 李华
网站建设 2026/10/5 10:21:50

axios和restful的区别是什么?

这是一个非常经典且容易让人混淆的问题。简单来说&#xff0c;它们根本不在同一个层面上&#xff0c;不能直接对比。打个比方&#xff1a;RESTful 就像是餐厅的菜单和点餐规则&#xff08;比如&#xff1a;用 GET 来看菜单&#xff0c;用 POST 来下单&#xff09;。Axios 就像是…

作者头像 李华