资讯动态

Web-Dev-For-Beginners:基于事件驱动编程从零构建打字速度游戏

发布时间:2026/9/7 18:13:27 来源:尧图企业网站定制
Web-Dev-For-Beginners基于事件驱动编程从零构建打字速度游戏【免费下载链接】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 课中你将通过构建一个能追踪打字速度与准确率的打字游戏系统掌握浏览器事件驱动编程的核心机制事件监听器event listener、addEventListener()、click与input事件的处理流程以及如何用 DOM 操作实现实时视觉反馈。读完本篇并动手完成后你将能够独立完成用户输入 → 事件分发 → 状态更新 → 界面反馈这一完整交互闭环并可进一步实现难度分级、排行榜等进阶功能。为什么 Web 编程是事件驱动的网站感知你点击按钮、输入文字的能力全部来自事件驱动编程event-driven programming。每一次点击、按键、鼠标移动浏览器都会向 JavaScript 代码发送一条消息——即事件event由你决定如何响应。Web 编程与传统脚本的最大差异在于不可预测性你无法预知用户何时点击按钮——可能立刻点可能等五分钟也可能根本不会点。因此不能像写菜谱那样从上到下线性执行而是让代码耐心地等待某件事发生。文档用了一个形象的类比这就像 19 世纪的电报员守在机器旁消息一到达就立即响应。那么什么算一个事件简单说就是发生的事情点击按钮是事件输入一个字母是事件移动鼠标也是事件。事件驱动编程的核心手段是event listener事件监听器——一种门铃安装门铃调用addEventListener()告诉它监听什么信号如click或keypress指定被触发时执行什么你的自定义函数。事件监听器的工作方式监听Listens特定的用户行为如点击、按键、鼠标移动在指定事件发生时执行Executes你的自定义代码立即响应Responds用户交互创造无缝体验通过不同的监听器处理Handles同一元素上的多个事件。注意创建事件监听器有多种方式——可以用匿名函数或命名函数可以用click属性这样的快捷方式也可以用addEventListener()。本课聚焦addEventListener()与匿名函数的组合因为这是 Web 开发者最常用的方式也是弹性最大的方式addEventListener()适用于所有事件事件名以参数形式传入。常用事件一览浏览器提供了几十种可监听的事件但大多数交互应用只依赖少数几个核心事件。浏览器官方文档MDN 的 Web Events 页面列出了完整清单——基本上用户在页面上的任何操作都会产生事件。以下几个是最常见的含本课使用的两个事件说明常见用途click用户点击了某个元素按钮、链接、交互元素contextmenu用户点击了鼠标右键自定义右键菜单select用户选中了部分文本文本编辑、复制操作input用户输入了文本表单校验、实时搜索理解这些事件类型的要点由用户与页面特定元素的交互触发Triggers通过事件对象提供Provides关于用户操作的详细信息让你能够构建Enables响应式、交互式的 Web 应用在不同浏览器和设备上行为一致Works。打字游戏的设计与总体流程本课要构建的游戏用于探索 JavaScript 中事件的工作方式测试玩家的打字能力——这是所有开发者都应有的一项常被低估的技能。顺带一提我们今天使用的 QWERTY 键盘布局是 19 世纪 70 年代为打字机设计的而良好的打字技巧对今天的程序员依然同样值钱游戏的整体流程如下游戏的工作方式玩家点击开始按钮时启动并显示一条随机名言逐词追踪玩家的打字进度实时高亮当前词语引导玩家注意力对打字错误提供即时的视觉反馈名言输入完成后计算并显示总耗时。文件结构与项目初始化保持干净的文件结构会让项目更专业。本项目只使用三个经典文件index.html页面结构、script.js游戏逻辑与事件监听器、style.css视觉样式。打开控制台或终端执行以下命令创建项目目录# Linux or macOS mkdir typing-game cd typing-game # Windows md typing-game cd typing-game这些命令的作用创建名为typing-game的新目录存放项目文件并自动进入该目录为你的游戏开发建立一个干净的工作区。然后打开 Visual Studio Codecode .该命令会在当前目录启动 VS Code把你的项目文件夹载入编辑器提供开发所需的全部工具。在 VS Code 中向该文件夹添加三个文件index.html—— 游戏页面的结构与内容script.js—— 全部游戏逻辑与事件监听器style.css—— 视觉外观与样式。构建用户界面先想清楚游戏需要什么如果你玩一个打字游戏屏幕上应该看到什么需求如下UI 元素用途HTML 元素Quote Display显示要输入的文字带idquote的pMessage Area显示状态与成功消息带idmessage的pText Input玩家输入名言的输入框带idtyped-value的inputStart Button开始游戏带idstart的buttonUI 结构的特点内容自上而下逻辑组织为元素分配唯一 ID 以便 JavaScript 定位提供清晰的视觉层次使用语义化 HTML 元素保障可访问性。每个元素都需要 ID 供后续 JavaScript 操作同时要在 HTML 中引用 CSS 与 JS 文件。创建index.html并加入以下内容!-- inside 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 !-- This will display our quote -- p idmessage/p !-- This will display any status messages -- div input typetext aria-labelcurrent word idtyped-value / !-- The textbox for typing -- button typebutton idstartStart/button !-- To start the game -- /div script srcscript.js/script /body /html这段 HTML 结构完成的事在head中链接 CSS 样式表创建清晰的标题与操作说明建立带特定 ID 的占位段落用于动态内容包含带可访问性属性aria-label的输入框提供触发游戏的开始按钮在页面末尾加载 JavaScript 文件以获得最佳性能确保 DOM 已就绪。启动应用Live Server开发中频繁测试能尽早发现问题。VS Code 有一个名为 Live Server 的扩展它会本地托管你的应用并在每次保存文件后自动刷新浏览器显著提升开发效率。安装步骤与使用方式通过 VS Code 扩展市场安装 Live Server 扩展点击 Install浏览器可能会引导你回到 VS Code安装过程中可能要求重启 VS Code安装完成后在 VS Code 中按Ctrl-Shift-PmacOS 为Cmd-Shift-P打开命令面板——它提供对所有 VS Code 命令的快速访问支持边输入边搜索输入 Live Server: Open with Live Server 并执行浏览器访问https://localhost:5500Live Server 默认本地地址即可看到你创建的页面。Live Server 的作用为项目启动本地开发服务器保存文件时自动刷新浏览器从本地 URL通常是localhost:5500提供你的文件。添加 CSS让反馈一目了然视觉反馈自计算早期就是用户界面的关键。我们的游戏必须让玩家立即知道该输入哪个词、出错时要马上看见。创建style.css并加入/* inside style.css */ .highlight { background-color: yellow; } .error { background-color: lightcoral; border: red; }这两个类的作用.highlight用黄色背景标出当前应输入的词语提供清晰的视觉引导.error用浅珊瑚色背景与红色边框标示打字错误提供即时反馈而不打断用户的输入流使用对比色保障可访问性与清晰的视觉传达。CSS 布局可以随意发挥——花点时间让页面更好看换字体、给标题上色、调整元素大小。仓库中的参考实现 solution/index.css 展示了如何在此基础上做完整美化.highlight与.error两个功能类保持不变另外的样式为#quote添加了左侧色条与圆角卡片背景index.css 第 54–65 行、为输入框加入聚焦时的发光过渡第 88–91 行、为开始按钮加入悬停上移动效第 113–116 行并包含 600px 断点的响应式规则第 139–156 行。这印证了一个要点游戏逻辑只依赖.highlight和.error两个 class 名视觉呈现可以自由发挥而无需改动 JavaScript。JavaScript让游戏活起来HTML 是车身CSS 是外观JavaScript 才是引擎。按以下三个步骤递进构建步骤目的学到的内容添加常量设置名言数组与 DOM 引用变量管理与 DOM 选取开始游戏的事件监听器处理游戏初始化事件处理与 UI 更新打字输入的事件监听器实时处理用户输入输入校验与动态反馈这种结构化方法帮助你把代码组织成逻辑清晰的分区增量构建功能便于调试理解应用各部分如何协作为未来项目积累可复用模式。先创建script.js然后逐步添加代码。第一步添加常量先准备齐所有资源。游戏需要的基本数据数据类型用途示例名言数组存储游戏所有候选名言[Quote 1, Quote 2, ...]词语数组把当前名言拆分为单个词[When, you, have, ...]词索引追踪玩家正在输入的词0, 1, 2, 3...开始时间计算耗时用于计分Date.now()同时需要三个 UI 元素的引用元素ID用途文本输入typed-value玩家输入处名言显示quote显示要输入的名言消息区message显示状态更新// inside script.js // all of our quotes 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., ]; // store the list of words and the index of the word the player is currently typing let words []; let wordIndex 0; // the starting time let startTime Date.now(); // page elements const quoteElement document.getElementById(quote); const messageElement document.getElementById(message); const typedValueElement document.getElementById(typed-value);这段初始化代码的设计意图用const存储福尔摩斯名言数组因为名言内容在运行期间不会改变用let初始化追踪变量words、wordIndex、startTime因为这些值会在游戏过程中更新通过document.getElementById()提前获取 DOM 元素引用以便高效访问用清晰的命名变量为全部游戏功能打下基础。技巧用document.getElementById()随时可以取回元素。由于这些元素会被反复引用用常量替代字符串字面量可以避免拼写错误Vue.js、React 等框架能帮你更好地集中管理这类引用。这个做法的价值在于防止多次引用时出现拼写错误描述性常量名提升可读性获得更好的 IDE 自动补全与错误检查日后元素 ID 变更时重构更容易。第二步开始游戏的事件监听器现在要写第一个真正的事件监听器。某处有个玩家终将点击Start按钮——可能是立刻可能是喝完咖啡之后——当它发生时你的游戏必须已经准备好。用户点击start时我们需要选取一条名言、初始化界面、设置当前词追踪与计时。// at the end of script.js document.getElementById(start).addEventListener(click, () { // get a quote const quoteIndex Math.floor(Math.random() * quotes.length); const quote quotes[quoteIndex]; // Put the quote into an array of words words quote.split( ); // reset the word index for tracking wordIndex 0; // UI updates // Create an array of span elements so we can set a class const spanWords words.map(function(word) { return span${word} /span}); // Convert into string and set as innerHTML on quote display quoteElement.innerHTML spanWords.join(); // Highlight the first word quoteElement.childNodes[0].className highlight; // Clear any prior messages messageElement.innerText ; // Setup the textbox // Clear the textbox typedValueElement.value ; // set focus typedValueElement.focus(); // set the event handler // Start the timer startTime new Date().getTime(); });代码逻辑分四块词追踪设置Word Tracking Setup用Math.floor(Math.random() * quotes.length)选取随机名言保证每局不同用split( )把名言切成单词数组把wordIndex重置为 0因为玩家从第一个词开始为新一轮游戏准备好状态。UI 设置与显示UI Setup and Display为每个词创建span元素使其可单独设置样式类把 span 数组连接成单个字符串一次性写入innerHTML高效完成 DOM 更新通过给childNodes[0]添加highlight类高亮第一个词清空上一局的消息提供干净起点。输入框准备Textbox Preparation清空输入框中的既有文本调用focus()将焦点设到输入框玩家可以立刻开始打字为新一局准备好输入区域下一节会在此注册input监听器。计时器初始化Timer Initialization用new Date().getTime()捕获当前时间戳等价于Date.now()支撑打字速度与完成耗时的精确计算。第三步打字输入的事件监听器这是游戏的核心每输入一个字母代码都会检查输入、给出反馈、决定下一步。它类似于 20 世纪 70 年代 WordStar 等早期文字处理软件为打字员提供实时反馈的方式。// at the end of script.js typedValueElement.addEventListener(input, () { // Get the current word const currentWord words[wordIndex]; // get the current value const typedValue typedValueElement.value; if (typedValue currentWord wordIndex words.length - 1) { // end of sentence // Display success 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) { // end of word // clear the typedValueElement for the new word typedValueElement.value ; // move to the next word wordIndex; // reset the class name for all elements in quote for (const wordElement of quoteElement.childNodes) { wordElement.className ; } // highlight the new word quoteElement.childNodes[wordIndex].className highlight; } else if (currentWord.startsWith(typedValue)) { // currently correct // highlight the next word typedValueElement.className ; } else { // error state typedValueElement.className error; } });理解打字逻辑的流程该函数采用瀑布式判断条件从最具体到最一般依次检查场景 1名言完成Quote Complete检查输入值与当前词相等且处于最后一个词wordIndex words.length - 1用当前时间减去开始时间计算耗时毫秒除以 1000 转换为秒显示含完成耗时的祝贺消息。场景 2一个词完成Word Complete当输入以空格结尾endsWith( )时检测到词结束用trim()验证去除空格后的输入与当前词完全一致清空输入框为新词做准备wordIndex自增前进到下一个词先移除所有 span 的 class再给新词加上highlight类完成视觉高亮的接力。场景 3正在正确输入Typing in Progress用currentWord.startsWith(typedValue)验证已输入部分是否为当前词的合法前缀移除任何错误样式表明输入正确允许玩家不被打断地继续输入。场景 4错误状态Error State当输入文本与期望词的前缀不匹配时触发给输入框应用errorCSS 类提供即时视觉反馈帮助玩家快速发现并纠正错误。注意判断顺序的讲究必须先检查整句完成再检查词完成——因为最后一词输入完成时不会再加空格若顺序颠倒最后一句永远无法判定完成。对照仓库参考实现同一逻辑的 ES6 重构版仓库在 solution/index.js 中提供了一份现代 ES6 重构版实现与教学代码逻辑一一对应适合作为完成后的对照阅读材料能印证上述事件处理链路的实际写法监听器注册方式更简洁solution/index.js 第 90–91 行直接用命名函数注册——startButton.addEventListener(click, startGame)与typedValueElement.addEventListener(input, handleTyping)替代教学版中的匿名箭头函数可读性更好且便于调试时定位函数名高亮逻辑收敛为单一工具函数highlightWord(index)第 44–48 行用el.classList.toggle(highlight, i index)一条语句同时完成清除旧高亮 设置新高亮而教学版需要显式循环清空再逐个赋值。从源码结构看两种写法等价但classListAPI 避免了直接操作className字符串覆盖其他类的潜在风险错误反馈更完整教学版只切换输入框的error类重构版在错误分支额外写入messageElement.textContent messages.error第 84–85 行把视觉反馈扩展到了消息区游戏结束后的状态控制完成时执行typedValueElement.disabled true第 73 行禁用输入框——这正是挑战部分UI State Management要求的做法防止玩家在完成后继续触发input事件计时 API 差异教学版用new Date().getTime()重构版用Date.now()二者返回相同的毫秒级时间戳可互换使用。此外solution/index.html 在可访问性上做了补充为输入框增加了隐藏的label fortyped-value第 53 行并配合 solution/index.css 中的.hidden-label视觉隐藏样式保证屏幕阅读器用户也能获得标签。这提示我们HTML 里aria-label之外label关联是更稳健的可访问性实践。测试你的应用现在你已从零构建出一个真实可用的打字游戏。测试要点点击 Start 确认显示随机名言确认打字时当前词被正确高亮确认拼错时出现错误样式确认完成一个词后高亮正确前进到下一词确认输入完整个名言后显示带耗时的完成消息。常见调试技巧用浏览器控制台F12查看 JavaScript 错误核对所有文件名是否完全一致大小写敏感确认 Live Server 正在运行并能正常刷新多测几条不同的名言验证随机选择是否生效。进阶挑战挑战一Copilot Agent 模式下的难度系统课程提供了一个面向 AI 编程助手的挑战使用 Agent 模式为打字游戏实现根据玩家表现动态调整的难度系统练习高级事件处理、数据分析与动态 UI 更新。提示词要求实现的系统应追踪玩家的打字速度每分钟词数与准确率百分比在 Easy简单名言、Medium现有名言、Hard含标点的复杂名言三个难度级别间自动切换在 UI 上显示当前难度级别与玩家统计实现连击计数器连续 3 次良好表现后提升难度为难度变化添加视觉反馈颜色、动画。需要补充相应的 HTML 元素、CSS 样式与 JavaScript 函数包含适当的错误处理并用 ARIA 标签保证可访问性。挑战二手工进阶功能功能说明练习的技能Input Control游戏完成时禁用input事件监听器点击按钮时重新启用事件管理与状态控制UI State Management玩家完成名言时禁用文本框DOM 属性操作Modal Dialog用模态对话框显示成功消息高级 UI 模式与可访问性High Score System用localStorage存储最高分浏览器存储 API 与数据持久化实现提示研究localStorage.setItem()与localStorage.getItem()实现持久化存储练习动态添加和移除事件监听器对应addEventListener/removeEventListener探索 HTMLdialog元素或 CSS 模态框模式考虑禁用/启用表单控件时的可访问性。其中完成后禁用输入监听器的做法在参考实现中已有雏形——solution/index.js 第 73 行在完成时disabled true你只需在此基础上补上点击 Start 时恢复监听与状态重置。掌握时间线接下来 5 分钟可以做的事用不同名言测试你的打字游戏确保运行顺畅尝试修改 CSS 样式——更换高亮色和错误色打开浏览器 DevToolsF12在游戏过程中观察 Console挑战自己以最快速度完成一条名言这一个小时可以完成的事向数组中添加更多名言可以来自你喜欢的书籍或电影实现挑战部分的 localStorage 最高分系统创建一个每分钟词数计算器在游戏结束后显示为正确输入、错误和完成添加音效一周的进阶路线构建支持好友同屏对战的多玩家版本创建具有不同名言复杂度的难度级别添加显示名言完成进度的进度条实现带个人统计追踪的用户账户设计自定义主题并允许用户选择样式一个月的蜕变目标创建逐步教授正确指法摆放的打字课程构建分析哪些字母或词导致最多错误的统计功能添加多语言和不同键盘布局支持集成教育类 API从文学数据库获取名言发布你增强后的打字游戏供他人使用课后作业创建你自己的键盘游戏学完本课基础后正式作业是设计并构建你自己的键盘游戏——可以是另一种打字游戏、按键绘像素的艺术应用、用方向键控制的街机小游戏或任何有创意的点子。要求见 Create a new keyboard game要求说明目的Event Listeners至少响应 3 种不同的键盘事件展示对事件处理的理解Visual Feedback对用户输入提供即时视觉响应展示 DOM 操作的掌握Game Logic包含计分、关卡或进度机制练习实现应用状态User Interface清晰的说明与直觉化的操作培养用户体验设计技能文档给出的创意方向包括节奏游戏按键配合音乐或视觉提示、像素艺术创作器不同键画不同颜色、单词构建器按特定顺序拼词、贪吃蛇方向键控制收集物品、音乐合成器不同键发不同音符、分类打字变体编程术语、外语、键盘鼓手按键映射鼓点。评分标准从四个维度展开功能完整度与流畅度、代码质量与事件处理效率、用户体验的可直觉性与反馈质量、创意与键盘事件运用的新颖程度。小结本节的收获可以浓缩为一条完整的事件驱动链路用addEventListener()为#start按钮注册click监听完成随机名言渲染、词高亮与计时启动为#typed-value输入框注册input监听通过前缀校验—词完成—句完成的瀑布式判断实时更新wordIndex、高亮与错误样式。这正是每个交互网站的底层机制——下次看到表单边输边校验、菜单随点击展开、游戏随按键响应时你都已经理解背后的原理了。完整课程脉络可参阅 Event-Driven Programming - Build a Typing Game动手练习则从 课后作业 开始。【免费下载链接】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),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价