这个文档/博客的目的是:了解其它项目使用的架构,进而个人项目的技术方案制定提供参考;帮助自己锻炼产品视角。使用豆包和通义千问辅助阅读,内容参考AI回复进行二次梳理。
组件库类
- https://github.com/youzan/vant-weapp
(一)项目类型:组件库
(二)主要功能位置:
项目的目录结构大致如下:
vant-weapp/ |
(三)亮点or没接触到的地方:
若要新增一个组件,流程如下:
创建组件目录
新增组件要放在packages
目录下。在该目录下创建文件夹my-component
与相关核心文件:packages/
my-component/
index.ts # 组件逻辑(属性、方法、生命周期等)
index.wxml # 组件模板
index.wxss # 组件样式
index.json # 组件配置(声明为自定义组件及依赖)微小
可能需要.wxs
demo/ # 组件示例(用于文档和演示)
index.ts
index.wxml
index.json配置组件依赖
在组件的index.json
中声明组件信息及依赖的其他组件(如van-icon
)开发环境验证
Vant Weapp 通过 npm 脚本和构建工具(如 rsbuild、vant-cli)实现打包,相关脚本可以在package.json
中的”scirpts”处查看:如npm run lint
:进行代码规范校验。
新增组件后,可先在示例工程中引入组件进行调试:- 在
example/pages
中创建示例页面,或在现有页面的json
中引入组件:{
"usingComponents": {
"van-my-component": "../../packages/my-component/index"
}
} - 运行开发命令实时编译:
npm run dev # 监听文件变化,实时生成开发版本
- 在
正式构建
确认组件无误后,执行构建命令生成发布版本:# 构建组件库(输出到 dist/ 和 lib/ 目录)
npm run build:lib查看构建成果
构建后会生成以下目录及文件,用于发布和使用:dist/
目录存放 ES6 版本的组件,保留完整的模块化结构,适用于支持 ES6 模块的环境。lib/
目录 存放 ES5 版本的组件,通过 Babel 转译,兼容更低版本的小程序基础库。
类型定义文件(TypeScript 类型定义文件.d.ts
) 存放于lib/definitions/
或组件目录中,它在构建过程中自动生成,存放于lib/definitions/
或组件目录中,支持类型提示。
构建成果最终会通过 npm publish
发布到 npm 仓库(包名 @vant/weapp
),开发者可通过 npm 安装使用新增组件。
(四)功能性能分析
- https://github.com/TooBug/wemark
(一)项目类型:微小的markdown-to-html组件
(二)主要功能位置:
(三)亮点or没接触到的地方:
(四)功能性能分析
项目demo类
(一)项目类型:类似知乎的内容平台
(二)主要功能位置:
列表数据展示: pages/index/ 和 pages/discovery/
下拉刷新与上拉加载更多: 同上
tab 切换:底部——app.json;顶部:
(三)亮点or没接触到的地方:
上拉刷新与下拉刷新,用showToast做好了操作响应;预留了网络请求。
// wxml |
在“发现”页面中,设置了顶部tab:
// wxml |
(四)功能性能分析
从这个项目,可以了解到小程序设计应该达到的要求:
1. **核心交互符合用户预期** |
https://github.com/giscafer/wechat-weapp-mapdemo
地图项目demo;暂不阅读。
(一)项目类型:日志
(二)主要功能位置:
pages中,entry查看日志详情;new进行日志编辑、list查看日志列表。
(三)亮点or没接触到的地方:
在demo/diaries.js
中,mock(模拟)了数据;
定义数据,然后 module.exports
。
const diaries = {}; |
(四)功能性能分析
a. 功能不足点:
创作流程断点:“日记可回溯修改” 的核心诉求
反馈缺失:操作后无明确提示(如保存日记、收藏成功等),无法确认操作是否生效
文本输入体验:长文本下频繁滚动
模态框交互:新建日记时的标题输入模态框(mine.wxml)无动画过渡,弹出 / 关闭生硬,影响操作流畅度
b. 性能优化方向:
性能问题:
- 数据加载与存储效率问题——一次性加载全部数据、本地存储设计缺陷(全部存储在单键上);
- 多媒体资源处理缺陷——未限制文件大小与格式:未对选择的图片 / 视频进行压缩或尺寸限制,直接存储原始文件路径
- 图片预览模式优化不足——预览swiper一次性渲染,导致初始化卡顿
- 页面渲染与生命周期管理问题——数据同步时机错误、无状态清理机制
- 网络请求与依赖管理问题——地图 API 请求未做缓存、无请求错误处理(没实现重试机制或错误降级策略,如网络异常时使用缓存数据)
优化方向:
优先级:异步数据依赖(避免白屏/错误)≈图片压缩(减少内存占用)> 分页加载列表数据(提升滚动流畅度)、拆分本地存储(优化读写效率) > 缓存地理位置、请求重试(优化网络体验)
- 数据加载与存储优化
实现分页加载
// 在 app.getDiaryList 中增加分页参数(page、size),列表页(list.js)初始只加载前 10 条,滚动到底部时触发下一页加载(结合 scroll-view 的 bindscrolltolower 事件)
// 示例:分页获取日记列表
getDiaryList: function(page = 1, size = 10, cb) {
// 从本地缓存/服务端按页读取数据
const start = (page - 1) * size;
const end = start + size;
const paginatedList = this.globalData.diaryList.slice(start, end);
cb(paginatedList);
}拆分本地存储结构
将单键存储改为按日记 ID 拆分存储(如 bearDiary_${id}),更新时仅操作单条数据,减少 IO 开销:
- 多媒体资源处理优化
- 图片/视频压缩与尺寸限制:
// 在 `new.js` 选择文件后,使用 `wx.compressImage` 压缩图片,限制视频时长和大小:
// 示例:压缩图片
chooseImage: function() {
wx.chooseImage({
success: (res) => {
res.tempFilePaths.forEach(path => {
wx.compressImage({
src: path,
quality: 80, // 压缩质量
success: (compressed) => {
// 使用压缩后的路径
this.writeContent({tempFilePaths: [compressed.tempFilePath]}, 'IMAGE');
}
});
});
}
});
} - 预览图片懒加载:
entry.js
的预览swiper仅初始化当前可见图片,滑动时动态加载前后2张,减少初始渲染压力(可借助小程序image
组件的lazy-load
属性)。
- 页面渲染与生命周期优化
- 修复异步数据依赖问题:通过回调后Promise链式调用,控制执行顺序
// 确保 `getMediaList` 在 `getDiary` 完成后执行,通过回调或Promise链式调用:
// entry.js 优化
onLoad: function(params) {
app.getDiaryList(list => {
// 获取日记详情
const diary = params.id ? list[params.id] : list[0];
this.setData({ diary }, () => {
// 数据更新后再获取媒体列表
this.getMediaList();
});
});
} - 清理页面状态:
// 在 `onUnload` 中重置数据,释放内存:
onUnload: function() {
this.setData({
diary: null,
mediaList: [],
previewMode: false
});
}
- 网络与缓存策略优化
- 缓存地理位置信息:
在 `app.js` 中缓存已获取的位置信息,有效期设为1小时,避免重复请求:
// 示例:缓存位置信息
globalData: {
locationCache: {
data: null,
expire: 0 // 过期时间戳
}
},
getLocation: function(cb) {
const now = Date.now();
if (this.globalData.locationCache.expire > now) {
cb(this.globalData.locationCache.data);
return;
}
// 重新获取并缓存
wx.getLocation({
success: (res) => {
this.globalData.locationCache = {
data: res,
expire: now + 3600000 // 1小时后过期
};
cb(res);
}
});
} - 增加请求重试机制:
// 在 `request.js` 中添加失败重试逻辑(限制重试次数):
// 带重试的请求封装
module.exports = (options, retry = 2) => {
return new Promise((resolve, reject) => {
const requestWithRetry = () => {
wx.request({
...options,
success: (res) => {
if (res.statusCode === 200) resolve(res.data);
else if (retry > 0) {
retry--;
requestWithRetry(); // 重试
} else reject(res);
},
fail: () => {
if (retry > 0) {
retry--;
requestWithRetry(); // 重试
} else reject();
}
});
};
requestWithRetry();
});
};