Web-Dev-For-Beginners 打字游戏实战:用事件驱动编程(Event-Driven Programming)打造实时打字速度测试
发布时间:2026/9/10 9:27:06来源:尧图网络
Web-Dev-For-Beginners 打字游戏实战用事件驱动编程Event-Driven Programming打造实时打字速度测试【免费下载链接】Web-Dev-For-Beginners24 Lessons, 12 Weeks, Get Started as a Web Developer项目地址: https://gitcode.com/GitHub_Trending/we/Web-Dev-For-Beginners本篇技术指南围绕开源课程《Web-Dev-For-Beginners》第 4 单元「事件驱动编程——构建打字游戏」展开完整讲解浏览器事件机制与addEventListener()用法并带你从零实现一个逐词校验、实时高亮、统计完成时间的打字游戏。读完你将掌握事件监听器工作原理、input/click事件的实战用法、DOM 动态渲染与四类键入状态判断逻辑并能直接运行仓库中的完整参考实现进行对照验证。从「事件」理解浏览器与 JavaScript 的对话网页之所以显得「活」且灵敏在于它对用户行为的即时响应每一次点击、滑动、键盘敲击浏览器都会向 JavaScript 代码发送一条「消息」这条消息就是事件event。事件驱动编程event-driven programming的核心并非自上而下按「菜谱」顺序执行代码而是让代码「耐心等待某件事发生」——就像 19 世纪守在发报机旁的报务员信号一来立即回应。Web 交互具有天然的不确定性用户可能立刻点击按钮也可能五分钟后才输入甚至根本不操作。因此代码必须通过注册**事件监听器event listener**来「预埋」响应逻辑。可以把监听器想象成代码的「门铃」安装门铃调用addEventListener()设定要听的「铃声」指定事件名例如click或keypress指定有人按铃后的动作传入你自己的回调函数事件监听器具备四个关键特性监听特定用户动作点击、按键、鼠标移动事件发生时执行你注册的自定义代码即时响应用户交互形成流畅体验同一个元素可通过多个监听器同时处理多种事件。说明创建事件监听器有多种途径——匿名函数或具名函数、直接给click等属性赋值、或使用addEventListener()。本课聚焦addEventListener()与匿名函数因为它是 Web 开发者最常用且最灵活的方式它对所有事件通用且事件名可作为参数动态传入。常见事件速查浏览器提供数十种可监听事件任何用户操作几乎都会触发事件但绝大多数应用只需少量基础事件。下表为常用事件含本游戏用到的两类事件描述常见用途click用户点击了某元素按钮、链接、可交互元素contextmenu用户右键点击自定义右键菜单select用户选中文本文本编辑、复制操作input用户输入了文本表单校验、实时搜索这些事件在用户与页面上特定元素交互时触发通过事件对象提供用户操作的详细信息支持构建响应式、交互式 Web 应用并在不同浏览器与设备上保持一致行为。游戏设计全局流程与运行规则打字是开发者的基础素养——今天使用的 QWERTY 键盘布局早在 1870 年代便为打字机设计。本课把这项技能训练做成游戏整体流程如下游戏运行机制归纳为五点点击 Start 按钮后开始并显示随机引言逐词实时跟踪玩家打字进度高亮当前应输入的单词以引导注意力输入出错时提供即时视觉反馈完成整段引言后计算并显示总用时。项目文件结构与开发环境游戏只依赖三个经典文件这「三件套」支撑了互联网上绝大多数页面index.html页面的结构与内容script.js全部游戏逻辑与事件监听器style.css视觉外观与样式在终端创建项目目录# Linux 或 macOS mkdir typing-game cd typing-game # Windows md typing-game cd typing-game用 VS Code 打开目录并创建上述三个文件code .用 Live Server 实时预览开发中高频测试能尽早暴露问题。VS Code 的Live Server扩展会在本地托管应用并在每次保存时自动刷新浏览器。安装后在 VS Code 中按Ctrl-Shift-PmacOS 为Cmd-Shift-P打开命令面板输入并执行Live Server: Open with Live Server。它会启动本地开发服务器、监听文件保存自动刷新并通常将页面托管在localhost:5500。随后在浏览器中打开http://localhost:5500即可看到页面。搭建用户界面index.html设计游戏界面需先明确玩家需要什么。所需 UI 元素及对应 HTMLUI 元素用途HTML 元素引言展示区显示待输入的文本pidquote消息区显示状态与完成消息pidmessage文本输入框玩家录入引言inputidtyped-value开始按钮启动游戏buttonidstart每个元素都需要唯一 ID 供 JavaScript 定位同时引入将要创建的 CSS 与 JS 文件!-- index.html -- html head titleTyping game/title link relstylesheet hrefstyle.css /head body h1Typing game!/h1 pPractice your typing skills with a quote from Sherlock Holmes. Click **start** to begin!/p p idquote/p !-- 显示引言 -- p idmessage/p !-- 显示状态消息 -- div input typetext aria-labelcurrent word idtyped-value / !-- 输入框 -- button typebutton idstartStart/button !-- 开始游戏 -- /div script srcscript.js/script /body /html结构要点head中通过link引入 CSS清晰的标题与操作指引带特定 ID 的空段落用于动态填充内容输入框带aria-label无障碍属性JS 置于/body前以优化加载性能。添加视觉反馈style.css视觉反馈对用户界面至关重要。游戏必须让玩家立即知道当前该输入哪个词、输错时能立刻察觉。基础样式只需两个类/* style.css */ .highlight { background-color: yellow; } .error { background-color: lightcoral; border: red; }含义.highlight用黄色背景高亮当前单词形成清晰的视觉引导.error用浅珊瑚色背景标记输入错误两色对比鲜明兼顾可访问性且不打断输入流。布局方面可自由发挥——换字体、给标题上色、调整尺寸。仓库中的美化版参考见 4-typing-game/solution/index.css它加入了渐变背景、圆角输入框、悬浮动效按钮与移动端媒体查询可作为「视觉打磨」的进阶范例。JavaScript 实现三步完成游戏引擎HTML 与 CSS 只是「车身」JavaScript 才是引擎。按以下顺序分步实现步骤目标所学技能创建常量配置引言数组与 DOM 引用变量管理与 DOM 选取开始游戏事件监听处理游戏初始化事件处理与 UI 更新打字输入事件监听实时处理用户输入输入校验与动态反馈第一步配置常量与 DOM 引用如同 NASA 发射前准备好全部监控系统开工前先备齐所有资源避免日后检索与拼写错误数据类型用途示例引言数组保存游戏中所有可用引言[Quote 1, Quote 2, ...]单词数组将当前引言拆分为单词[When, you, have, ...]单词索引跟踪玩家正在输入的单词0, 1, 2, 3...开始时间计算用于计分的耗时Date.now()UI 元素引用文本输入框typed-value玩家输入处、引言展示quote显示待输文本、消息区message状态更新。// script.js // 全部引言 const quotes [ When you have eliminated the impossible, whatever remains, however improbable, must be the truth., There is nothing more deceptive than an obvious fact., I ought to know by this time that when a fact appears to be opposed to a long train of deductions it invariably proves to be capable of bearing some other interpretation., I never make exceptions. An exception disproves the rule., What one man can invent another can discover., Nothing clears up a case so much as stating it to another person., Education never ends, Watson. It is a series of lessons, with the greatest for the last., ]; // 保存单词列表与当前正在输入的单词索引 let words []; let wordIndex 0; // 起始时间 let startTime Date.now(); // 页面元素 const quoteElement document.getElementById(quote); const messageElement document.getElementById(message); const typedValueElement document.getElementById(typed-value);设计意图引言用const声明因为内容不会改变跟踪变量用let因为游戏过程中其值会更新通过document.getElementById()缓存 DOM 引用以提高访问效率。把元素引用存入常量可避免反复引用时的拼写错误、提升可读性、获得 IDE 自动补全与错误检查、并在元素 ID 变更时简化重构。提示document.getElementById()可随时获取元素。由于这些元素会被频繁引用用常量封装有助于规避字符串字面量的笔误。Vue.js、React 等框架可帮你更好地集中管理这类代码。你还可以自行添加更多引言扩充游戏。第二步开始游戏逻辑click 监听器玩家点击start时代码需要随机选引言、准备 UI、设置当前单词与计时跟踪。第一个真正的事件监听器由此诞生// script.js 末尾 document.getElementById(start).addEventListener(click, () { // 获取一段引言 const quoteIndex Math.floor(Math.random() * quotes.length); const quote quotes[quoteIndex]; // 将引言拆成单词数组 words quote.split( ); // 重置单词索引用于跟踪 wordIndex 0; // UI 更新 // 创建 span 元素数组便于设置类名 const spanWords words.map(function(word) { return span${word} /span}); // 拼接为字符串并赋给引言展示的 innerHTML quoteElement.innerHTML spanWords.join(); // 高亮第一个单词 quoteElement.childNodes[0].className highlight; // 清空先前的消息 messageElement.innerText ; // 设置输入框 // 清空输入框 typedValueElement.value ; // 设置焦点 typedValueElement.focus(); // 启动计时器 startTime new Date().getTime(); });分四部分理解这段逻辑 单词跟踪设置用Math.floor()Math.random()随机取索引选引言保证每局不同split( )将引言转为单词数组wordIndex重置为 0玩家从第一个词开始完成新一局的游戏状态准备。 UI 设置与展示用map()为每个单词生成span包裹元素以便单词级独立设样式join()拼成单个字符串一次性写入innerHTML高效更新 DOM给首个 span 加highlight类完成首词高亮清空上一局消息提供干净开局。⌨️ 输入框准备清空输入框已有文本调用focus()让玩家无需点击即可立刻开始打字。⏱️ 计时器初始化用new Date().getTime()捕获当前时间戳为后续精确计算打字耗时奠基。第三步打字逻辑input 监听器这是游戏心脏每输入一个字符代码都要检查内容、给出反馈并决定下一步。与 1970 年代 WordStar 等早期文字处理器给打字员实时反馈同理// script.js 末尾 typedValueElement.addEventListener(input, () { // 获取当前单词 const currentWord words[wordIndex]; // 获取当前输入值 const typedValue typedValueElement.value; if (typedValue currentWord wordIndex words.length - 1) { // 句子结束 // 显示成功消息 const elapsedTime new Date().getTime() - startTime; const message CONGRATULATIONS! You finished in ${elapsedTime / 1000} seconds.; messageElement.innerText message; } else if (typedValue.endsWith( ) typedValue.trim() currentWord) { // 单词结束 // 清空输入框准备下一个词 typedValueElement.value ; // 前进到下一个单词 wordIndex; // 重置引言中所有元素的类名 for (const wordElement of quoteElement.childNodes) { wordElement.className ; } // 高亮新单词 quoteElement.childNodes[wordIndex].className highlight; } else if (currentWord.startsWith(typedValue)) { // 目前输入正确 typedValueElement.className ; } else { // 错误状态 typedValueElement.className error; } });该函数采用「瀑布式waterfall」判断从最精确到最一般逐层检查。对应流程图四种场景逐一拆解 场景一引言完成——校验输入值与当前词相等且已到最后一个词用当前时间减去开始时间得到耗时除以 1000 把毫秒换算为秒显示带完成时间的祝贺消息。✅ 场景二单词完成——当输入以空格结尾时判定本词结束用trim()去掉空格后须与当前词精确匹配清空输入框迎接下一个词wordIndex推进索引先清空引言内所有 span 的类再给新词加highlight。 场景三输入进行中——用currentWord.startsWith(typedValue)校验已输入前缀是否与目标词开头一致若一致则移除error类恢复常态允许玩家不停顿继续输入。❌ 场景四错误状态——当输入文本与期望词的开头不符时进入给输入框加上error类立即呈现浅珊瑚色背景帮助玩家快速定位并修正错误。完整参考实现对照仓库为每课提供了完整可运行版本位于 4-typing-game/solution。对照阅读可加深理解index.jsES6 重构版将本课内联匿名函数拆分为具名函数startGame、handleTyping抽出getRandomQuote()、renderQuote()、highlightWord()等纯函数用classList.toggle()替代逐节点改className并把消息统一收敛到messages对象——这是本课逻辑在生产风格代码中的自然演进逻辑分支完成判定、空格结束单词、前缀匹配、错误态与原版一一对应。index.html在基础结构上补充了视觉隐藏的label、placeholder、Font Awesome 图标与实时日期时间显示展示可访问性与细节打磨思路。index.css.highlight与.error两个核心类与课程一致lightcoral用border-color: red并叠加完整视觉主题与响应式布局。顺带一提课程配套作业 4-typing-game/typing-game/assignment.md 要求自创一款基于键盘事件的新游戏至少响应 3 种不同键盘事件、提供即时视觉反馈、具备计分/关卡等机制并给出韵律游戏、像素画创作、单词拼写、贪吃蛇、键盘鼓手等创意方向与详细评分标准可作为事件驱动编程的进阶练习。测试你的应用点击start并开始打字游戏运行效果可参考下图动画重点验证五项行为点击 Start 是否显示随机引言正确输入时是否高亮当前单词输错时是否出现错误样式完成单词后高亮是否正确前移整段完成是否显示带用时的消息。常见调试建议打开浏览器控制台F12检查 JavaScript 报错核对所有文件名是否完全一致大小写敏感确认 Live Server 正在运行且能正常刷新页面多试几段引言验证随机选取是否生效进阶挑战与拓展方向用 Agent 模式实现难度自适应系统借助 GitHub Copilot Agent 模式完成如下挑战为打字游戏实现依据玩家表现自动调节的难度系统——跟踪打字速度每分钟单词数WPM与正确率百分比在三个难度档自动切换Easy 用简单引言、Medium 用当前引言、Hard 用含标点的复杂引言在 UI 展示当前难度与玩家统计实现连续计数器——连续 3 次良好表现后提升难度用颜色、动画等视觉反馈标识难度变化。实现时需新增相应 HTML 元素、CSS 样式与 JS 函数并保证错误处理完善、用 ARIA 描述维持无障碍访问。四项进阶功能清单功能描述可练习的技能输入控制完成时禁用input事件监听器点击按钮后重新启用事件管理与状态控制UI 状态管理玩家完成引言后禁用输入框DOM 属性操作模态对话框用模态弹窗展示成功消息进阶 UI 模式与可访问性最高分系统用localStorage持久化保存最高分浏览器存储 API 与数据持久化实现提示研究localStorage.setItem()/localStorage.getItem()实现持久化练习动态添加与移除事件监听器探索 HTMLdialog元素或 CSS 模态模式在禁用/启用表单控件时兼顾无障碍体验。自我学习路径建议5 分钟用不同引言测试游戏调整.highlight与.error颜色开着 DevTools 控制台边玩边观察。1 小时扩充引言数组可用喜欢的书或电影台词按挑战实现 localStorage 最高分系统编写每局结束显示的 WPM 计算器为正确输入、错误与完成添加音效。一周做双人并排对战版本实现不同引言复杂度的难度档添加引言完成进度条实现带个人统计的用户账号设计可切换的自定义主题。一个月做含指法进阶课程的打字教程用数据分析哪些字母/单词错误率最高支持多语言与键盘布局接入教育类 API 从文学数据库拉取引言将成品发布供他人使用。总结事件驱动编程是让 Web「活起来」的核心概念之一——下拉菜单、随输入实时校验的表单、对点击即时响应的游戏其底层机制你都已掌握。本课通过打字游戏这一载体打通了「事件监听器注册 → DOM 动态渲染 → 逐词输入校验 → 实时视觉反馈 → 用时统计」的完整链路。想深入可研读浏览器提供的全部事件类型并思考各自的适用场景再对照仓库 solution 的完整实现用作业 assignment.md 检验自己的创造力与编码能力。【免费下载链接】Web-Dev-For-Beginners24 Lessons, 12 Weeks, Get Started as a Web Developer项目地址: https://gitcode.com/GitHub_Trending/we/Web-Dev-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网