简介:微信小程序期末大作业「记单词小程序」是一份面向初学者的完整项目源码,覆盖微信开发者工具使用、WXML/WXSS页面搭建、JavaScript业务逻辑、数据绑定、生命周期、组件化、网络请求与本地存储等核心知识点,适合作为课程设计或自学练手项目。压缩包共96个文件,包含32个png图片、17个json配置文件、17个js脚本、14个wxss样式、13个wxml页面结构文件及license、txt说明文档,整体大小约833KB,目录结构清晰,便于按模块阅读和二次开发。资源已有3018人学习下载,可帮助初学者从需求分析到编码发布完整走通小程序开发流程。通过单词卡片、复习测试等交互功能,学习者可直观理解页面渲染与数据交互机制,并可直接运行调试、扩展功能,为后续更复杂的移动应用开发打基础。
1. 从零把这个记单词小程序搭到能跑
期末大作业选“记单词小程序”是个聪明选择:需求清楚、用户就一个人、不需要复杂权限,做成什么样一眼可演示。但不少初学者选完题之后卡在第一关——不知道先写哪部分,也不知道哪些功能必须做、哪些可以省。常见做法是:小程序前端页面按时做完了,但单词数据写死在 JS 里,复习进度存在全局变量里,一关页面全没,答辩时被问两句就接不上话。
这篇顺着“记单词小程序”这个标题,把方案拆成能直接落地的五步:先定技术路线,然后把数据层设计好,再实现列表页、背诵卡片页、学习记录与进度,最后把项目整理成可提交的期末作业样子。全程围绕微信小程序开发者工具和云开发跑,不依赖自建服务器,你用现有微信开发者工具就能一步步复现。如果你只是找一份“微信小程序源码”改改交差,我也把改哪些地方、为什么改写在对应章节里,比全盘抄代码更有底气。
2. 记单词小程序的数据层:云数据库和本地缓存怎么分工
2.1 为什么推荐云开发而不是本地 JSON 文件
很多期末作业示例喜欢把单词数组直接塞进data里,几十条数据确实够用。但记单词小程序最少需要一个能存“用户学到哪了”的地方。wx.setStorageSync能存本地,可换手机或删缓存就丢;而且答辩时老师大概率会问“你的数据是静态的还是动态的”,回复“写死在代码里”评分会打折扣。
我推荐的做法是:用微信小程序云开发的云数据库存单词表,用本地 Storage 存学习进度。单词表是公共只读数据,放在云端方便你后期加词不重新发版;学习进度是私有数据,存本地最快,等需要做“多端同步”或“账号系统”时再迁移到云数据库。对初学者来说,这个分工兼顾了演示效果和开发量。
云开发不需要自己买服务器,开通后在开发者工具里点“云开发”按钮初始化环境即可。首次开通会创建默认环境,记下环境 ID,后面初始化要用。
2.2 单词集合的字段设计:直接照着建表
在云开发控制台创建集合,名字建议叫words。每篇文档对应一个单词,字段尽量精简,合理的最小结构是这样:
| 字段 | 类型 | 说明 | 示例值 |
|---|---|---|---|
word | string | 英文单词 | abandon |
phonetic | string | 音标 | /əˈbændən/ |
meaning | string | 中文释义,分号分隔 | v. 放弃;抛弃 |
example | string | 例句 | He abandoned the plan. |
exampleCn | string | 例句翻译 | 他放弃了那个计划。 |
category | string | 可选,按词性/专题分组 | cet4 |
order | number | 排序权重,供列表页排序 | 1 |
其中word建议加索引并设为唯一,防止不小心插入了重复词条。order字段很多人忽略,没有它列表就只能按默认规则排,新增单词会乱插,列表页体验不稳定。
2.2.1 一条可直接导入的示例数据
控制台选择“words”集合,点“添加记录”,用 JSON 模式粘贴:
{ "word": "abandon", "phonetic": "/əˈbændən/", "meaning": "v. 放弃;抛弃", "example": "He abandoned the plan.", "exampleCn": "他放弃了那个计划。", "category": "cet4", "order": 1 }云开发控制台的“导入”功能支持 JSON/CSV 文件批量导入。如果你手里有一份现成的四六级词汇表,用脚本转成这种结构再导入,比在控制台手工录入快得多。字段名不一定要完全一样,但前后端要严格对齐,这是初学者最常见的翻车点:页面取的是meaning,数据库里存的是translation,跑起来白屏。
2.3 进入页面时拉取单词表的最小代码
在app.js里先做云环境初始化,再在单词列表页onLoad时拉数据。下面这段是初学阶段比较稳妥的写法:
// app.js App({ onLaunch() { if (!wx.cloud) { console.error('请使用 2.2.3 以上版本的基础库以使用云能力'); } else { wx.cloud.init({ env: 'your-env-id', traceUser: true }); } } });页面里拉取单词列表:
// pages/index/index.js Page({ data: { words: [], loading: true }, async onLoad() { const db = wx.cloud.database(); const res = await db.collection('words') .orderBy('order', 'asc') .limit(20) .get(); this.setData({ words: res.data, loading: false }); } });limit(20)是用来控制小程序的单次拉取上限的,云数据库默认单次最多返回 20 条。如果你要一次拿出全量词表,常见做法是加wx.cloud.callFunction走云函数,或者分批游标循环拉取。期末作业场景建议先limit(20)跑通,再去研究云函数分页,别一上来就把难度拉满。
3. 从列表到背诵卡片:两个核心页面的实现要点
3.1 单词列表页的三层结构:模板、数据、样式
微信小程序页面由 WXML、JS、WXSS 三件套组成。列表页的核心是用wx:for循环渲染words数组。一个适合初学者的 WXML 结构大致长这样:
<view class="word-list"> <view class="word-item" wx:for="{{words}}" wx:key="word" bindtap="goDetail" >goDetail(e) { const word = e.currentTarget.dataset.word; wx.navigateTo({ url: '/pages/detail/detail?word=' + word }); }这里有两个细节容易踩坑。第一,wx:key不要写成wx:key="{{word}}",直接写字段名即可。第二,>Page({ data: { word: '', phonetic: '', meaning: '', example: '', exampleCn: '', showAnswer: false, currentIndex: 0, wordList: [] }, onLoad(options) { const word = decodeURIComponent(options.word || ''); this.fetchWord(word); }, async fetchWord(word) { const db = wx.cloud.database(); const res = await db.collection('words') .where({ word }) .get(); if (res.data.length > 0) { const item = res.data[0]; this.setData({ word: item.word, phonetic: item.phonetic, meaning: item.meaning, example: item.example, exampleCn: item.exampleCn }); } } });
where({ word })是等值查询,云数据库里word字段建立了唯一索引后用这个查询很快。不建索引也能跑,但数据量大了后在控制台会看到查询耗时明显上升。索引创建位置在云开发控制台“数据库-索引管理”里,字段名选word,选唯一,方式选“唯一索引”。老师如果追问“你的查询用了索引吗”,你能答上这一步会明显加分。
3.3 “认识 / 不认识”按钮:setData 与进度更新
这是记单词小程序的关键交互。每张卡片底部放两个按钮,点击后记录结果,同时用setData刷新当前页面的卡片。认识按钮的典型逻辑是:
markKnown() { const { word, wordList, currentIndex } = this.data; this.saveRecord(word, true); this.nextCard(wordList, currentIndex); }, markUnknown() { const { word, wordList, currentIndex } = this.data; this.saveRecord(word, false); this.nextCard(wordList, currentIndex); }, nextCard(list, index) { if (index < list.length - 1) { this.setData({ currentIndex: index + 1, showAnswer: false }); this.fetchWord(list[index + 1].word); } else { wx.showToast({ title: '本轮学习完成', icon: 'success' }); } }setData在这里的作用是同步更新视图层数据,即每次切换卡片要重置showAnswer为false,否则翻到下一张时会直接显示上一张的释义,很影响体验。另外,像markKnown这类事件处理函数里使用wx.showToast时,注意跳转新页面后 toast 会停留在旧页面,最佳实践是在onHide里调用wx.hideToast()兜底。
4. 学习记录与复习排序:让小程序看起来像一个完整产品
4.1 本地 Storage 的结构:每天学过的词都记下来
记单词小程序如果做完形填空式的交互却没有记录,答辩时会被追问“背过的单词下次还会出现吗”。为了避免这种尴尬,至少要有学习记录。存储结构挂上日期字段,方便做“今日学习 X 词”的统计:
// 数据结构示意 { "2025-06-10": [ { "word": "abandon", "count": 1, "known": true }, { "word": "typical", "count": 2, "known": false } ] }写入本地缓存时注意要先把旧的取出来再合并,不能整体覆盖。原因是缓存读写是异步的,如果两次setStorageSync连续执行,后一次可能覆盖先前的数据。初学者最常见的写法是这样:
saveRecord(word, known) { const today = this.getToday(); const storageKey = `records_${today}`; let records = wx.getStorageSync(storageKey) || []; const found = records.find(r => r.word === word); if (found) { found.count += 1; found.known = known; } else { records.push({ word, count: 1, known }); } wx.setStorageSync(storageKey, records); }getToday返回YYYY-MM-DD格式字符串,可以用new Date()拼一个基础版本。这里有个细节:手机时区变化会导致日期错误,如果你在真机调试发现记录存到了“昨天”,检查一下系统时间或者用getTime()配套处理时区,这是微信小程序开发者工具模拟器与真机差异的典型问题。
4.2 用“错词优先”做一轮简单的复习排序
完整的记忆算法很复杂,期末作业阶段实现一个“错词优先 + 复习间隔”的简化逻辑就足够拿分了。思路是:把当天记录里known为false的词,在下一轮学习时排到最前面;连续三天都记住的词,暂时不加入待学列表。这个逻辑在拉取单词后、界面渲染前处理:
async loadTodayWords() { const db = wx.cloud.database(); const todayWords = await db.collection('words') .limit(20) .get(); const records = wx.getStorageSync('records_' + this.getToday()) || []; const unknownWords = records.filter(r => !r.known).map(r => r.word); const sorted = [...todayWords.data].sort((a, b) => { const aUnknown = unknownWords.includes(a.word) ? 0 : 1; const bUnknown = unknownWords.includes(b.word) ? 0 : 1; return aUnknown - bUnknown; }); return sorted; }这个排序有两个需要留意的点:第一,sort返回的是新数组,todayWords.data本身没有被修改,如果不理解这一点,可能在翻阅源码时产生困惑,进而去改顺序导致副作用;第二,limit(20)之外的单词不会出现在列表里,如果词库很大,应该用云函数一次性取全部单词再在本地排序,避免频繁请求云数据库。
4.3 用进度条让“学习进度”可视化
光标上方的进度条不是花架子,它直接让老师一眼看懂这个记单词小程序完整闭环了。用progress组件绑定学习进度即可:
<view class="progress-wrap"> <progress percent="{{progressPercent}}" stroke-width="4" activeColor="#07C160" backgroundColor="#eeeeee" border-radius="2" /> <view class="progress-tip">今日已完成 {{finishedCount}} / 共 {{totalCount}} 词</view> </view>对应 JS 里计算百分比:
calcProgress() { const total = this.data.wordList.length; const finished = this.data.currentIndex; this.setData({ progressPercent: total === 0 ? 0 : Math.round(finished / total * 100) }); }进度记录建议在markKnown和markUnknown里都调用一次,保持视图时刻同步。如果你用的旧版本基础库不显示border-radius,那是组件属性和样式兼容性问题,不需要专门处理,调研时只要保证基础库版本不低于 2.10.0 即可。
5. 期末作业的收尾细节:演示顺畅、图片齐全、代码能答辩
5.1 把写死的 words 数组替换成云数据库的完整流程
如果你拿到的示例代码里单词直接写在data里,换成云数据库时要改三处:app.js的wx.cloud.init环境 ID、列表页的onLoad数据源、背诵卡片页的fetchWord查询函数。改完记得在控制台创建words集合并导入数据,不然页面一拉取就报collection not exists。
这里有个检查技巧:在开发者工具的“云开发”控制台左侧点“数据库”,如果确实没有集合,就手动创建同名集合;如果集合存在但列表空,检查是权限问题还是导入格式问题。几乎所有“页面空白 + 控制台报-501000之类错误”的博客案例,最后都指向这里。
5.2 模拟一个完整的背诵流程供演示
答辩时最怕演示翻车。我一般建议准备两个环境:开发者工具模拟器作为主要演示环境,同时把真机调试开起来备用。演示流程固定在 1 分钟以内:打开列表页 → 点进第一个词 → 点“显示释义” → 点“不认识” → 看进度条前进 → 退出重进确认记录还在。这套流程在模拟器和真机上都跑一遍,能覆盖这小程序 80% 的核心功能。
5.3 三个最容易在答辩现场暴露的问题
第一,页面传参忘记decodeURIComponent,点进卡片后word为undefined。第二,新增单词后列表顺序乱跳,没有在数据库里维护order字段。第三,使用wx.cloud.database().collection时未初始化环境,报Cloud API isn't enabled。把这三个点写进你的项目说明文档里,作为“遇到的问题与解决方案”,会比单纯罗列功能更有说服力。
5.4 让代码在被查看时加分的两个小习惯
给关键函数写注释,说明输入输出,比如saveRecord(word, known)上方写“记录单个单词的记忆结果,known=true 表示认识,false 表示不认识”。把页面里的全部.js文件统一加上use strict。代码缩进统一,用 2 空格而不是 Tab。老师翻源码时第一眼看到的不是功能而是整洁度,这两个习惯直接影响印象分。
本文还有配套的精品资源,点击获取