要用 AI 做学习工网页,最容易低估的反而是需求拆得不够细。一开始我以为不过是把单词卡、口算题丢给 AI,让它吐一个 HTML 页面出来就算完事。真跑过几轮之后发现,一套稳定的做法要从“需求描述 → 提示词 → 代码生成 → 本地验证 → 数据批量替换”走完整,才能做到真正拿来即用。
这篇就当记录一次完整的实践过程。标题写“纯炫耀,不卖课”,确实没有卖课计划,也不是在推销模板,只是把当前跑通的一套方法拆开讲清楚。如果你正好也想给自家孩子、自己备考、或者给学生做一点轻量学习小工具,下面这些内容可以直接照着试。
1. 核心能力速览
先用一张表把“用 AI 做学习小网页”这件事的关键属性列清楚。
| 能力项 | 说明 |
|---|---|
| 项目类型 | AI 辅助开发的学习工具网页集合 |
| 技术栈 | HTML + CSS + JavaScript,纯静态页面,无后端 |
| 启动方式 | 浏览器直接打开本地 .html 文件,或部署为静态网站 |
| 主要功能 | 单词记忆卡片、口算练习、选择题自测、错题回顾、学习打卡 |
| 硬件门槛 | 几乎为零,普通电脑和手机均可访问 |
| 运行成本 | 0 元,静态页面不依赖服务器,可以离线使用 |
| 是否支持接口 API | 默认不需要。如需 AI 实时出题,要自己接入模型服务接口 |
| 是否支持批量任务 | 支持。让 AI 一次生成多套题目,或通过脚本批量注入数据 |
| 适合场景 | 个人学习、教学演示、轻量级知识自测、小范围分享 |
从这张表能看出,这个方向的定位不是做一个“产品级应用”,而是用最低成本验证一个学习想法能不能跑通。我曾经试过在这个流程里引入 Vue 组件、引入后端数据库,结果为了一个只能自己用的错题本,反而花了大量时间处理环境问题。后来把技术栈砍到只剩浏览器原生能力,整个项目反而稳定很多。
2. 学习网页能覆盖哪些实际场景
这类纯静态学习网页能覆盖的场景,比多数人预想的要宽。这里列一部分实际做过的类型。
2.1 背单词与记忆卡片
最常见的类型。把单词数据放在数组里,页面每次渲染一张卡片,点击翻转显示释义,支持上一张、下一张、随机复习。这个场景的技术复杂度很低,但对交互体验要求高。卡片翻转动画、按钮位置、手机端触控区域都会影响实际使用。
我做过的一个词卡页面,初始需求只是“看单词想释义”,后来逐步加了“标记生词”“只看生词”“乱序复习”三个功能。每次新增需求都回到 AI 对话框,用自然语言描述,让 AI 修改代码,基本没有手写过复杂逻辑。
2.2 数学口算与专项练习
口算页面适合低年级学生。页面随机生成两位数的加减法,输入答案后立即判断对错,底部显示正确率。这个场景对 AI 生成能力几乎没有挑战,重点在于出题范围控制。提示词里要明确写明“两位数以内”“不出现负数”“结果不超过 100”,否则 AI 生成的题目经常超出范围。
2.3 选择题与知识点自测
这个场景更接近考试模式。一组题目,每题四个选项,选中后立即反馈对错,最后统计得分。这类页面需要的数据结构比单词卡复杂一点,需要保存题目、选项、正确答案、解析四个字段。如果让 AI 一次性生成 20 道完整题目,经常出现选项重复或者正确答案漏标的情况,所以更稳妥的做法是先让 AI 生成一个通用的题目渲染框架,再用 JSON 数据填充题目内容。
2.4 错题回顾与学习记录
错题本页面不一定要连接数据库。用浏览器自带的 localStorage 就能保存错题数据,页面关闭再打开,记录仍然存在。这个方案虽然没有云端同步,但对单机使用场景已经足够。我在做错题本时发现一个问题:浏览器存储一旦清掉缓存,错题记录也会消失。可以考虑增加一个导出功能,把错题数据导出成 JSON 文件,或者复制成文本保存。
2.5 边界在哪里
这套方式也有明显边界。它是纯静态页面,没有账号系统,没有多人协作,没有云端同步,不适合做需要教师批改、学习进度上报、班级管理的完整教学系统。另外,如果学习内容需要动态更新,比如每天从服务端拉取最新题库,也超出了纯 HTML 的适用范围。
内容层面还有一个必须提醒的边界:不要用 AI 直接生成盗版教材、盗版题库,也不要拿未经授权的图片、音频、视频做学习素材。学习工具本身没问题,但素材来源必须合规。
3. 环境准备与前置条件
这个流程对环境和硬件的要求已经压到了最低。
3.1 操作系统与浏览器
Windows、macOS、Linux 都可以。浏览器建议用 Chrome 或 Edge,因为它们的开发者工具比较完善,调试页面问题时更方便。手机端用系统自带浏览器基本也能打开,不过要留意布局是否适配。
3.2 AI 工具
需要一个可以生成代码的对话式 AI 网页端,目前主流的大模型对话工具基本都有免费额度,生成几百行的单文件 HTML 不是问题。这类任务关键是提示词写清楚,而不是模型参数调多高。不需要本地部署大模型,普通配置电脑完全够用。
3.3 编辑器
做简单修改也可以用自带记事本,但强烈建议装一个 VS Code。原因不只是写代码方便,而是 VS Code 右下角会显示编码格式,能避免文件用 GBK 编码保存导致中文乱码的问题。
3.4 可选本地服务器
严格来说,纯 HTML 文件双击就能打开,不需要服务器。但如果页面里用到 fetch 加载本地 JSON 文件,浏览器会限制本地文件访问,这时需要一个简单的静态服务器。可以用 VS Code 的 Live Server 插件,也可以在项目目录下运行:
# Python 3 自带静态服务器,在当前目录启动 python -m http.server 8080然后在浏览器访问http://localhost:8080。后面做数据批量注入时会用到这个方式。
4. 从一句话到学习网页的完整流程
整个流程可以分为五个步骤:需求描述、提示词撰写、代码生成、本地保存、验证迭代。
4.1 先明确需求
这步会被很多人跳过,但恰恰最影响结果。不要直接对 AI 说“帮我做一个背单词网页”,而是先自己回答几个问题:
- 这份学习工具是给谁用的?
- 在电脑上打开还是手机上打开?
- 学习内容是从哪里来的,固定数据还是动态生成?
- 需要记录学习结果吗?
回答完这四个问题,需求基本就清楚了。
4.2 写提示词
提示词要具体到页面布局、交互逻辑、数据位置。下面是一个可复用的模板:
你是一个前端开发工程师。请写一个单文件 HTML 页面,功能是“单词速记卡片”。 需求如下: 1. 页面标题为“四级高频词卡片”。 2. 每张卡片显示英文单词、音标。 3. 点击卡片可以翻转,背面显示中文释义和例句。 4. 页面底部有“上一张”“下一张”“随机复习”按钮。 5. 所有单词存放在一个名为 wordList 的数组里,方便我后续替换数据。 6. 样式要求:卡片在页面居中,按钮明显,手机端可以正常点击。 7. 一次输出完整 HTML 代码,不要输出解释。 单词数据: [ { "word": "abandon", "phonetic": "/əˈbændən/", "meaning": "放弃;抛弃", "example": "Never abandon your dream." } ]这段提示词里最关键的有三点:指定单文件、指定数据位置、要求完整输出。把数据单独放在数组里,后续替换成 100 个单词都非常快。
4.3 生成与保存
AI 输出代码后,不要直接全选复制到 Word 里。正确做法是新建文件,文件名用英文或数字,比如word-card.html,编码选 UTF-8,把代码粘贴进去保存。文件后缀必须是.html,不是.txt。双击文件,浏览器打开,页面正常渲染说明第一步成功。
4.4 验证与迭代
页面能打开只是开始,要达到真正能用,还要逐项验证:单词数据是否完整、翻卡是否正常、按钮是否有效、手机端是否错位。如果发现问题,直接复制报错信息回到 AI 对话框,要求它修改。迭代速度非常快,因为问题大多集中在局部逻辑。
4.5 一个完整的单词卡片示例
下面这段代码是一个最小可用的单词卡片页面,是我用 AI 辅助调过两轮之后的版本,可以直接复制运行。
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>四级高频词卡片</title> <style> body { font-family: system-ui, sans-serif; max-width: 640px; margin: 0 auto; padding: 24px; background: #f7f8fa; text-align: center; } .card { min-height: 260px; background: #ffffff; border-radius: 16px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); display: flex; flex-direction: column; align-items: center; justify-content: center; margin-bottom: 24px; cursor: pointer; transition: transform 0.2s ease; padding: 20px; user-select: none; } .card.flipped { transform: rotateY(180deg); } .word { font-size: 32px; font-weight: 700; } .phonetic { color: #777; font-size: 16px; margin-top: 8px; } .meaning { font-size: 22px; margin-top: 16px; color: #333; } .example { font-size: 14px; color: #888; margin-top: 12px; } .btn-group button { font-size: 16px; padding: 10px 20px; margin: 6px; border: none; border-radius: 8px; background: #3b82f6; color: #fff; cursor: pointer; } .btn-group button:nth-child(2) { background: #10b981; } .btn-group button:nth-child(3) { background: #f59e0b; } #index { color: #999; font-size: 14px; margin-bottom: 12px; } </style> </head> <body> <h2>四级高频词卡片</h2> <div id="index">1 / 1</div> <div class="card" id="card"> <div class="word" id="word">abandon</div> <div class="phonetic" id="phonetic">/əˈbændən/</div> <div class="meaning" id="meaning" style="display:none;">放弃;抛弃</div> <div class="example" id="example" style="display:none;">Never abandon your dream.</div> </div> <div class="btn-group"> <button onclick="prevCard()">上一张</button> <button onclick="nextCard()">下一张</button> <button onclick="shuffle()">随机复习</button> </div> <script> const wordList = [ { word: "abandon", phonetic: "/əˈbændən/", meaning: "放弃;抛弃", example: "Never abandon your dream." }, { word: "ability", phonetic: "/əˈbɪləti/", meaning: "能力", example: "She has the ability to lead." }, { word: "absorb", phonetic: "/əbˈzɔːb/", meaning: "吸收;吸引", example: "Plants absorb water from the soil." } ]; let current = 0; let flipped = false; const card = document.getElementById('card'); const wordEl = document.getElementById('word'); const phoneticEl = document.getElementById('phonetic'); const meaningEl = document.getElementById('meaning'); const exampleEl = document.getElementById('example'); const indexEl = document.getElementById('index'); function render() { const item = wordList[current]; wordEl.textContent = item.word; phoneticEl.textContent = item.phonetic; meaningEl.textContent = item.meaning; exampleEl.textContent = item.example; meaningEl.style.display = 'none'; exampleEl.style.display = 'none'; flipped = false; card.classList.remove('flipped'); indexEl.textContent = (current + 1) + ' / ' + wordList.length; } function flip() { flipped = !flipped; meaningEl.style.display = flipped ? 'block' : 'none'; exampleEl.style.display = flipped ? 'block' : 'none'; card.classList.toggle('flipped', flipped); } function nextCard() { current = (current + 1) % wordList.length; render(); } function prevCard() { current = (current - 1 + wordList.length) % wordList.length; render(); } function shuffle() { current = Math.floor(Math.random() * wordList.length); render(); } card.addEventListener('click', flip); render(); </script> </body> </html>把wordList里的数据换成自己的单词,这个页面就能直接变成一份词汇复习工具。AI 生成的代码可能会在细节上有出入,但整体逻辑基本一致。
5. 四类典型学习网页的生成与验证
用前面这套流程,可以快速生成不同类型的学习页面。每个类型都按“生成提示词 → 运行页面 → 判断是否成功 → 处理异常”的路径验证。
5.1 单词记忆卡片
测试目的是确认单词展示、卡片翻转、翻页按钮正常。输入素材是 10 到 20 个单词的数据数组。操作步骤是双击打开 HTML,依次点击上一张、下一张、翻卡、随机复习。
判断标准很直观:单词与释义是否对应、翻卡动画是否生效、是否会出现单词越界。常见失败原因是 AI 生成的数组格式错误,多了一个逗号或者引号不全,页面直接白屏。处理方式是把控制台报错信息复制给 AI,让它修复。
5.2 数学口算练习
给 AI 的提示词示例:
写一个单文件网页,功能是“两位数加减法口算练习”。 每次随机生成一题,数字范围在 10 到 99 之间,答案为非负整数。 页面顶部显示当前题目,下方是输入框和“提交答案”按钮。 提交后立刻显示对错,并更新正确率和做题数。 每题做完自动生成下一题,不需要手动点击下一题。 一次输出完整 HTML。这个页面的成功标准是:连续做 20 题不会出现负数结果,正确率计算准确,提交空值时不会报错。最容易踩的坑是 AI 生成负数答案,因为提示词没写“答案非负整数”,所以在提示词里加限制条件是必须的。
5.3 选择题自测
选择题页面适合准备考试类场景。提示词里要明确给出题目数据结构:
题目数据用数组存储,每个对象包含: question: 题目标题 options: 四个选项组成的数组 answer: 正确答案的索引,从 0 开始 explanation: 答案解析 页面显示题目和四个选项按钮,点击选项后高亮正确答案,错误选项标红,展示解析。 底部有“下一题”和“结束测验”按钮,结束页显示得分与正确率。验证时用一组 5 到 10 题的数据,人为把某题答案改成错误值,确认页面是否能正确判断。这里要特别留意正确答案索引是否从 0 开始,AI 偶尔会生成从 1 开始但下标又按 0 读取的逻辑,导致判断错位。
5.4 错题回顾
错题页面我的做法是把错题数据保存在 localStorage 里,用 AI 生成两个按钮:“加入错题本”和“导出错题记录”。导出功能可以手动复制文本,也可以生成一个可下载的文本文件,后者体验更好一点。
验证方法是做错一道题,加入错题本,刷新页面,确认记录还在。如果记录丢失,优先检查浏览器是否禁用了 localStorage,或者代码里把数据存储到了 sessionStorage 而不是 localStorage,这两者只在页面会话时长上有区别,刷新后结果完全不同。
6. 批量生成题目与数据注入
单个页面做好之后,下一步要考虑的是怎么批量生成题目数据。
6.1 让 AI 一次生成多套数据
对话式 AI 的上下文长度有限,一次塞 500 道题很容易让输出截断。更稳定的做法是分批生成,比如每次 20 道,分 5 批。提示词可以这样写:
继续生成下一批 20 道题,数据结构与上一批保持一致,题目不要与之前重复。每次生成完把数据追加到同一个数组里,这样可以拼接出一套百题规模的题库。
6.2 用 JSON 数据驱动页面
更工程化的方案是把题目数据单独抽到一个data.js文件,页面用<script src="data.js"></script>引入。这样做的好处是页面逻辑和数据完全分离,以后更新题目不需要动页面代码。
例如单词页面里,把wordList这个数组放到word-data.js文件里:
window.wordList = [ { word: "abandon", phonetic: "/əˈbændən/", meaning: "放弃;抛弃", example: "Never abandon your dream." } ];页面内部不再定义数组,而是读取window.wordList。更新单词时,只改数据文件,页面不动,大大降低误操作概率。
6.3 用脚本批量转换现有题库
如果手里已经有一份 Excel 或 CSV 格式的题库,可以让 AI 写一个转换脚本,把表格数据变成 JSON 数组。这里给一个通用思路,详细脚本需要根据实际表格格式调整:
import csv import json # 按实际文件路径调整 with open("words.csv", "r", encoding="utf-8") as f: reader = csv.DictReader(f) words = [] for row in reader: words.append({ "word": row["word"], "phonetic": row["phonetic"], "meaning": row["meaning"], "example": row["example"] }) with open("word-data.js", "w", encoding="utf-8") as f: f.write("window.wordList = ") f.write(json.dumps(words, ensure_ascii=False, indent=2)) f.write(";")运行后生成的word-data.js可以直接被页面引入。注意 CSV 文件里的列名要和row["word"]对应,否则会报 KeyError。
6.4 是否需要真正接入 API
这些学习页面默认不需要 API。但如果想把 AI 实时出题能力直接集成进页面,比如每次都生成不同题目,那就要接模型服务商的接口。这里有两个建议:
- 不要直接在纯前端页面里暴露 API Key,跨域和安全性都不好处理。
- 如果一定要接入,用后端服务转发请求,前端只调用自己的后端接口。
对个人学习场景来说,先离线做好几十道题已经足够,真没必要把大模型接到每个小页面里。
7. 资源占用与性能观察
这套方案的资源占用几乎可以忽略。单文件 HTML 一般在几 KB 到几十 KB,浏览器打开后的内存占用很低,老旧电脑和低端手机都能流畅运行。
真正影响体验的其实是两个环节:一是 AI 生成代码的等待时间,二是页面内图片和外部依赖的加载时间。如果页面引入了外部 CDN 的字体、图标库或框架文件,加载速度会明显变慢,而且离线时无法使用。所以我的做法是尽量让页面自给自足,不依赖任何外部资源。
观察性能的方法很简单,打开浏览器开发者工具,在 Performance 面板点击 Record,然后操作页面几秒钟,查看是否有长时间占用的任务。静态页面一般不会出现明显卡顿,如果出现,多半是循环逻辑写得太差,比如遍历一个超大数组时每次都操作 DOM。遇到这种情况,把代码片段发给 AI 优化即可。
如果打算部署到公网,可以选择 GitHub Pages、Gitee Pages、Cloudflare Pages 这类静态托管服务,上传一个 HTML 文件就能生成访问链接。个人使用不需要买服务器。
8. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 双击 HTML 后页面空白 | 文件后缀不是 .html,或代码不完整 | 检查文件名后缀和浏览器控制台报错 | 新建 .html 文件,重新粘贴完整代码 |
| 中文显示乱码 | 文件保存编码不是 UTF-8 | 用编辑器查看右下角编码格式 | 另存为 UTF-8 编码 |
| 单词翻不了卡 | JS 语法错误或事件绑定问题 | 打开控制台看报错信息 | 将报错信息发给 AI 修复 |
| 按钮点击后没反应 | 按钮函数未定义或拼写不一致 | 检查 onclick 是否和 JS 函数名一致 | 统一函数名 |
| 手机上布局错乱 | 没有加 viewport 标签 | 查看 head 里是否有 meta viewport | 加上 viewport 并调整 CSS 宽度 |
| localStorage 数据丢失 | 浏览器清理缓存或改用隐私模式 | 检查代码里用的是 localStorage 还是 sessionStorage | 统一使用 localStorage,并提醒用户不要清缓存 |
| AI 生成的题目答案有误 | 提示词没有约束数据规则 | 抽查题目的正确性 | 在提示词里加上“必须保证答案正确”,关键数据人工复核 |
| 本地打开时加载不了本地 JSON | 浏览器安全策略限制 | 无法直接用 file 协议加载 | 改用本地静态服务器,或把数据写到 data.js 里 |
| 页面能打开但没样式 | CSS 被 AI 放在错误位置或未保存完整 | 检查 head 中是否有 style 标签 | 重新生成代码 |
| 部署到托管平台后 404 | 文件路径或文件夹名错误 | 检查仓库文件名是否为 index.html | 将入口页面命名为 index.html |
这些问题的共性特征是:大部分都能通过浏览器控制台找到线索。看到红色报错不要慌,复制报错信息回传给 AI,它通常能指出问题代码的位置。
9. 最佳实践与使用建议
9.1 提示词做成模板
同一类页面可以用固定模板,减少每次描述成本。模板要包含:技术栈、页面功能、交互逻辑、数据结构、输出格式要求。用模板生成的页面代码风格统一,后续迭代也更方便。
9.2 保持一个可运行的最小版本
每完成一个功能,就把当前能跑通的版本保存一份,不要在一个版本上无限叠加功能。保存方式可以是单独文件夹,也可以在文件名加版本号。这样做的好处是即使后续改崩了,随时可以回退到一个稳定版本。
9.3 数据与页面逻辑分离
把学习数据抽到独立文件里,页面只负责展示和交互。这是整套流程中最值得坚持的一条。数据分离后,更新题目、调整知识点,都不需要碰页面逻辑,改出错的风险小很多。
9.4 隐私与合规
使用 AI 生成学习内容时,注意不要上传包含个人身份信息的学生名单、考试成绩等敏感数据。如果必须上传,先做脱敏处理。内容本身也要注意版权:不要直接把别人的付费课程、试卷、教材原文丢给 AI 生成,更不要做成网页后对外传播。学习工具可以辅助记忆和理解,但内容的合法来源始终要守住。
9.5 生成后必须人工复核
AI 生成的内容并不是 100% 正确,尤其是理科题目的答案、概念解释、例题解法。建议生成后全部过一遍,或者至少抽样检查。给学习工具用,答案错了会造成误导,这个责任不能全部甩给 AI。
9.6 控制功能范围
一次只做一个核心功能。做一个口算工具,就先别急着加历史记录、排行榜、多人对战。每加一个功能,AI 生成的代码复杂度都会上升,表面看是效率变低,实际是 bug 排查成本变高。把单一功能做稳定,比同时堆五六个功能更有价值。
9.7 离线优先
学习工具很可能要在没有网络的环境里使用,比如自习室、考场周边。尽量把页面做成单文件、无外部依赖,这样收藏到手机里也能随时打开。依赖 CDN 的页面一旦断网就会退化为白屏,得不偿失。
10. 总结与下一步
这套“用 AI 做学习小网页”的流程,最值得尝试的点是它把学习工具的开发门槛降到了极低:不用配置环境,不用学框架,有一台普通电脑和浏览器就能开始。建议第一次验证时,从最基础的单词卡片做起,跑通“生成 → 修改 → 运行”这三步,你就会发现后续所有学习页面都是同一个套路。
最容易踩的坑集中在三个地方:一是提示词没写清楚数据结构和操作逻辑,生成结果反复返工;二是直接把 AI 输出保存到 Word 或记事本,导致编码和格式问题;三是数据没有与页面逻辑分离,后期改题都要动代码。把这三件事在第一次就用对,后面的项目会顺畅很多。
后续想继续深化,可以把多个小页面整合成一套个人学习工具集,或者把数据文件统一到一个目录,配合脚本做批量更新。如果哪天对本地数据同步产生了需求,再考虑加一个轻量后端也不迟。绝大部分个人学习场景,纯静态页面已经足够。