做微信小程序开发这几年,踩过的坑比吃过的盐还多。这个系列笔记我一直在坚持写,第三篇本来想偷懒,结果这几个月又攒了一堆东西——从框架选型到UI适配,从登录鉴权到审核上架,每个环节都有值得记录的新问题和老坑。这篇笔记我尽量按主题整理,覆盖我在实际开发中遇到的高频问题,包括列表加载更多、顶部导航栏适配、uni-app打包体积超限的处理、抓包调试技巧、订阅消息授权、蓝牙定位,还有几个典型项目比如校园食堂订餐系统、家政服务平台的核心设计思路。适合正在做小程序开发、尤其是刚入门没多久的朋友,也欢迎老手一起交流。
1. 项目框架与多端打包
1.1 原生框架与uni-app怎么选
这个选择题我几乎每一次新项目都要面对一次。微信原生小程序开发框架(WXML/WXSS/JS)和uni-app框架是目前最主流的两条路线。原生框架的优势不用多说,API调用直接、WePY和Taro这些也都有自己的选择,但最核心的问题在于:你是不是只做微信小程序一个端。我个人的判断标准很简单——如果项目明确要求同时覆盖微信小程序、支付宝小程序、抖音小程序、H5或者App,那就直接上uni-app,它是Vue语法体系,一套代码多端编译,配合HBuilderX开发和云打包,效率确实高。如果只是做一个微信小程序、长期迭代,而且团队里有人比较熟悉原生语法,那原生反而更稳,因为微信开发者工具对原生项目的调试体验是最完整的,很多API的自动补全和报错提示只有原生环境给得最清楚。
但要注意,uni-app虽然号称一套代码多端运行,实际开发过程中还是会遇到平台差异需要写条件编译,比如uni-app在小程序端的页面生命周期和App端并不完全一致,onReachBottom在App端偶尔会不触发,还有蓝牙、wifi这类硬件API在不同平台的兼容性也不同。我的建议是:能用官方API就用官方API,跨端需求用条件编译圈起来单独处理,不要幻想一份代码全端跑通不用改。
另外,最近看到不少人在讨论uniapp做小程序打包时遇到体积超限的问题,这个我放在下面单独说,因为那是真坑。
1.2 打包体积超限的实战处理
微信小程序对主包体积的限制是2MB,这个限制对原生开发者来说已经比较紧张,对uni-app开发者来说更容易触发。我见过一个最典型的报错信息:source size 2612kb exceed max limit 2mb,意思是编译后的代码体积已经超过2MB上限。这个报错会在开发者工具上传代码时直接卡住你,无法提交预览和体验版。
解决思路要分两步走:一是从源头削减包体积,二是合理利用分包机制。先说削减体积。uni-app项目里最容易撑爆包体的是三个东西:UI组件库、图表库、图片资源。比如你觉得vant-weapp好用就全局引入了,结果光组件库就占掉大几百KB;又比如你引用echarts做柱状图,全量echarts.min.js动不动就1MB以上。我的做法是:组件库按需引入,官方文档里都有easycom规则,可以做到组件在使用时才打包编译进入最终产物;图表这类重库尽量换成轻量方案;图片资源必须走CDN,不要把本地图片放在static目录里,也不要走base64转码,代码包里每一KB都很珍贵。
再说分包。微信小程序的分包机制是官方给的逃生舱,可以在app.json里配置subPackages,把页面和静态资源拆分到分包里。用户访问主包页面时不会加载分包代码,进入分包页面时才动态下载对应代码。这样主包体积可以控制在1.5MB以内,留出余量给核心功能。uni-app里同样支持分包配置,在pages.json中配置subPackages节点即可。需要注意的是,分包之间不能互相引用文件,公共代码尽量放到主包里;分包的根目录也不能直接访问主包里的私有资源。这个限制操作上经常被忽略,踩了就会有报错提示,最好一开始就规划好哪些页面放主包、哪些放分包。
1.3 小程序游戏开发的基本路径
小程序游戏和普通小程序不是一个赛道,做的技术栈也不太一样。小程序游戏没有WXML和WXSS,渲染方式是Canvas和WebGL,逻辑层使用JavaScript或者TypeScript,整体开发方式更像H5游戏。现在Express(白鹭)、Cocos Creator都支持发布到微信小游戏平台,LayaAir也有对应的构建流程。如果你是做轻量休闲游戏,强烈推荐用Cocos Creator,素材管理和场景编辑都成熟,构建出来就是微信小游戏的工程目录,直接放到微信开发者工具里打开就能调试。
我第一次做小游戏的时候犯了个错误——想用原生canvas API硬写一套简单的小游戏框架。结果写了几百行代码之后发现连精灵动画都没有实现,后来果断切到Cocos Creator,两三天时间就把核心玩法做完了。我的观点是:小游戏开发不要把时间浪费在底层造轮子上,如果想学习底层原理当然可以去研究渲染循环、碰撞检测,但商业项目必须用成熟引擎。微信小游戏平台还提供了一套开放的API,包括开放数据域、排行榜、社交分享、虚拟支付等能力,这些是H5游戏没有的,做商业化产品时一定要提前规划。
2. UI细节与常用组件的坑
2.1 顶部导航栏高度计算与自定义导航栏适配
微信小程序的默认导航栏用起来简单,但如果你想做沉浸式视觉效果、把页面背景色延伸到导航栏区域,或者需要自定义右上角按钮的交互,就必须使用自定义导航栏。做法是在页面的json配置里设置"navigationStyle": "custom",这样系统就不会自动渲染导航栏,需要自己写一个导航栏组件。
这里最大的坑是高度适配。不同手机的状态栏高度不一样,胶囊按钮(就是右上角那两颗圆形按钮)的位置也不一样。我的做法是使用wx.getWindowInfo()获取statusBarHeight(状态栏高度),再使用wx.getMenuButtonBoundingClientRect()获取胶囊按钮的位置信息。自定义导航栏组件的高度通常等于“状态栏高度 + 胶囊按钮高度 + 胶囊按钮上下间距”的总和。简洁起见可以直接把胶囊按钮的top值当成导航栏内容的顶部边距,再用bottom - top算出导航栏可放置内容的高度区间。iPhone X以上的机型还需要考虑底部安全区,否则自定义的底部按钮或者TabBar会被Home Indicator遮挡。
关于自适应还有一个细节:在自定义导航栏模式下,页面顶部不要放互动性强的元素,比如轮播图、横向滚动标签,因为你计算好的导航栏高度在部分安卓机型上会有1~2像素偏差,原因通常是状态栏高度在不同机型上存在差异。遇到这种情况不要慌,加一个状态栏占位view,高度动态绑定为statusBarHeight即可,效果稳得很。
2.2 单选框组件与表单联动实践
单选框在原生小程序里用的是radio-group和radio标签对。写起来很简单,一个radio-group绑定bindchange事件,里面放多个radio,每个指定value和label。但实际开发中最容易出问题的点在于样式定制——原生radio的外观在iOS和安卓上渲染不一致,间距和圆点大小也不同。如果你需要完全一致的自定义样式,建议隐藏原生圆形图标,自己用view来模拟选中和未选中状态,配合CSS的::after伪元素画对勾,这样两个平台的表现就能统一。
另一个常见的坑是在表单场景里,单选框值的变化不会自动触发表单重置。比如用户填了一堆信息,选择了单选项A,之后点击重置按钮,输入框的值清空了,但单选框还停留在已选中状态。解决方案是在重置函数里手动管理radio-group的值,把绑定的数据字段重置为初始值,而不是只清空输入框。还有一个跟picker组件的对比:如果选项比较多(超过5个),不要用单选按钮而是用picker的selector模式,弹出滚动选择器体验更好,也节省页面空间。
2.3 搜索框聚焦偏移问题排查
搜索框聚焦后偏移是我在移动端遇到过好几次的神奇Bug。具体表现是:页面顶部的搜索框用position: fixed固定在顶部,点击输入框聚焦、弹出软键盘之后,整个搜索框会向上或者向下偏移,甚至搜索框跟随键盘移动。这个问题的根本原因是软键盘弹出导致WebView的视口(viewport)尺寸发生变化,fixed定位元素的包含块可能因此受影响,尤其在安卓WebView上表现最明显。
我的排查思路和解决方案是这样:第一步,检查搜索框是不是真的用position: fixed定位,如果是,尝试改为页面正常流布局,让搜索框放在页面最上方,不脱离文档流,这样键盘弹出时它不会跟着跑。第二步,如果页面需要滚动且搜索框必须悬浮,可监听onKeyboardHeightChange事件,手动计算键盘高度,动态设置搜索框的bottom或transform偏移,把位置修正回来。第三步,检查输入框的adjust-position属性,小程序里input组件的这个属性默认是true,意味着键盘弹出会自动上推页面,如果你的搜索框在顶部,需要把这个属性设为false,再手动处理位置逻辑。
这个Bug在iOS上出现的概率低一些,但也不是没有。一句话总结:凡是搜索框、输入框这种带聚焦交互的组件,尽量避免复杂定位,越简单越稳定。
2.4 图表与视频组件的实现细节
小程序里做柱状图、折线图这种数据可视化,最常见的方案是ec-canvas,它是ECharts官方适配小程序的组件。基础用法是把ec对象传给ec-canvas组件,在ec的option里写图表配置。用的时候有几个细节要注意:一是ec-canvas默认有延迟加载的问题,如果多个图表同时渲染,会出现空白或者闪烁,建议给不在首屏的图表设置lazyLoad,滚动到可视区域再初始化;二是图表容器的尺寸不能是100%,因为小程序里canvas的宽高必须在初始化时指定为具体像素值,我一般用wx.createSelectorQuery()动态获取容器实际宽高再传给图表;三是别忘了在页面卸载时调用dispose释放canvas资源,尤其是页面频繁跳转的场景,不释放可能导致内存持续增长。
视频组件live-player和video组件在PC端表现有明显差异。live-player的全屏按钮在PC端微信里点击没有反应,原因是桌面端微信底层并不支持live-player的全屏API。我的做法是在PC端点击全屏按钮时降级为页内全屏——不调用原生全屏,而是通过cover-view盖一层沉浸式黑底容器,让视频组件的宽高铺满窗口,模拟出全屏效果。如果你用video组件,PC端的fullscreenchange事件支持情况也好一些,但依然建议在PC端预览时做好降级逻辑,不要让用户点了个寂寞。
3. 核心功能与API实战
3.1 列表加载更多的完整实现
页面列表加载更多大概是列表类小程序里出现频率最高的功能需求,微信原生的方案已经做得比较顺手了。流程是这样的:在页面json中开启"onReachBottomDistance"(默认值是50px),然后页面里使用onReachBottom生命周期函数,当用户滚动到接近底部时触发加载。我在每个列表页的数据模型里维护三个核心字段:list(已加载的数据数组)、page(当前页码,从1开始)、hasMore(是否还有更多数据)。每次请求时带上page和pageSize,接口返回数据后,list进行数组拼接,page加1,hasMore根据返回数据条数判断——如果返回的条数小于pageSize,就说明没有更多数据了。
实现过程中容易踩的坑有三个:一是onReachBottom在安卓和iOS上触发的灵敏度不同,如果你的页面内容高度不够一屏,根本不会触发,这种情况要加一个兜底逻辑,比如在onReady之后主动判断内容高度是否撑满视口,没撑满就直接加载第二页;二是防止重复请求,用户快速滚动时onReachBottom可能触发多次,这就需要用一个isLoading标志位做拦截,请求返回之前不允许再次发起;三是加载状态的体验设计,底部要显示“加载中”、“没有更多了”的状态提示,这个状态样式我用的是一个简单的view加上文字和转圈动画,比直接空白要专业得多。
还有一个常被忽略的地方:onReachBottom是页面纬度的,不一定每个页面都适合。如果你的页面是长列表且内部还有横向滚动区域,要提前做好事件隔离,避免横向滑动误触到底部加载逻辑。
3.2 登录鉴权流程与wx.login
微信小程序的登录鉴权是每个项目绕不开的环节。常规流程就是用wx.login()获取一个临时code,这个code有效期是5分钟,而且只能用一次。拿到code之后,前端把它发给自己的后端服务器,后端再拿这个code去微信的接口code2Session换取openid、session_key等信息,随后后端生成自己的登录态token返回给前端。前端后续所有请求都带上token,后端校验token识别用户身份。
这里有两个容易踩的坑:第一,不要把code直接存起来,它是一次性的,滥用会造成登录失败。第二,不要在客户端保存openid和session_key,session_key是敏感信息,应该由后端保管,用于解密手机号、用户信息等敏感数据。前端的持久化存储只需要存token,登录态过期时后端返回401,前端再自动调用wx.login重新静默登录即可。
我再补充一个细节:很多开发者把wx.login和wx.getUserProfile混在一起理解,以为必须授权用户信息才能登录。实际上wx.login是静默登录,不需要弹窗授权;wx.getUserProfile才是用户主动点击授权的触发动作。现在微信调整了用户隐私规则,用户信息授权按钮需要由用户主动点击触发,不要再尝试在页面onLoad里直接调用获取用户信息接口了,那个弹窗已经不允许了。绝大多数业务只需要wx.login拿到用户身份就够了,头像昵称这种资料可以引导用户后续完善,而不是在登录时强行拦截。
3.3 监听用户离开小程序的生命周期处理
监听用户离开小程序,实际涉及两个维度:一个维度是页面被销毁(比如用户从当前页跳转到其他页面),另一个维度是整个小程序退到后台或者被用户关闭。页面维度用onUnload和onHide;小程序整体后台化则使用App实例的onHide生命周期,但有一点要注意,App.onHide不仅在小程序切后台时触发,在小程序被扫码关掉、微信本身切后台时也会触发,所以触发条件要结合自己的业务仔细判断。
一个典型应用场景是:用户在填写表单过程中突然切到微信聊天界面回了个消息,再次回到小程序时,页面可能被回收了,草稿数据丢了。处理办法是在onHide里把草稿数据通过wx.setStorageSync写入本地缓存,在onShow时读取并恢复。还有视频和音频播放场景,在onHide时要自动暂停播放,避免用户离开后声音还在响,这是微信平台审核时比较关注的问题。另外,如果你的项目做了“监听用户离开后发送通知”的联动,记住小程序并没有真正“关闭”的概念,用户回到微信首页并不代表小程序立即销毁,它可能还驻留在后台内存里一段时间,所以依赖页面销毁去做数据上报并不可靠。
3.4 订阅消息授权与蓝牙定位要点
订阅消息是替代模板消息方案出现的,现在小程序只有订阅消息这一种推送能力。它分成两种类型:一次性订阅消息和长期订阅消息。一次性订阅消息用户每次点击授权只能允许你发送一条消息,再次推送需要再次点击授权;长期订阅消息则要求小程序在特定类目下才能申请,形如政务、医疗、交通等。对大部分普通小程序来说,基本只能用一次性订阅消息。
授权弹框必须在用户点击行为中触发,wx.requestSubscribeMessage不能在页面加载时直接调用,否则弹框不会出现,还会返回错误信息。实操上我一般会设计一个“开启通知”按钮,用户主动点击后弹出授权请求,然后在小程序后台配置模板ID和跳转路径。这里有个体验细节要注意:不要让用户每次进入都看到授权请求弹框,如果用户已经拒绝过了,再弹就是骚扰了,合理的策略是记录授权状态,只对没有决定过的用户显示按钮。另外,订阅消息的模板内容可以使用动态参数,比如拼团成功通知里的订单号和商品名,参数拼接要在后端生成模板数据,前端只提供用户的openid。
蓝牙定位的实现路径大概是:wx.openBluetoothAdapter初始化蓝牙模块,然后wx.startBluetoothDevicesDiscovery开始搜索附近设备,监听wx.onBluetoothDeviceFound拿到设备列表,再筛选出对应的iBeacon或者蓝牙信标设备,通过信号强度(RSSI)估算距离。蓝牙定位往往还需要结合Wi-Fi指纹或者基站信息做混合定位才有实际可用性。开发时还要注意iOS系统要求蓝牙权限必须在app.json中声明用途,否则会在调用蓝牙接口时直接报错。
4. 调试工具链与真机测试
4.1 使用抓包工具分析小程序请求
调试小程序网络请求,我一般还是依赖抓包工具辅助。以Charles为例,基本思路是:让手机和电脑连到同一局域网,设置手机WiFi代理指向电脑IP和Charles的8888端口,然后给手机安装Charles的SSL证书,在Charles里为*.qq.com、*.weixin.qq.com以及你调试的API域名开启SSL Proxying。配置完成之后,手机上小程序的每一个HTTPS请求都能在Charles里看到完整的request和response,包括请求头、POST参数、JSON响应体。
实际调试中,抓包最有用的场景有两个:一个是排查接口数据异常,后端说“我这边返回是对的”,前端说“我请求了但数据不对”,这时候用抓包结果说话,看真实发出去和返回来的字节流,问题一眼就清楚;另一个是调试第三方平台(比如地图API、支付回调)的报文格式,自己看报文比问客服高效得多。
要注意的是,小程序真机调试时如果启用了域名校验,必须把请求域名加到开发者后台的request合法域名列表中,否则抓包请求直接报错。另外,小程序前端代码一般会被压缩混淆,直接看请求里的参数名字基本能猜到含义,但接口逻辑要根据后台日志来综合定位。
4.2 开发者工具分发与试用反馈收集
微信开发者工具里做完一个版本后,想把小程序发给其他人试用、收集反馈,有两种典型操作路径:第一种是直接点击工具栏的“预览”按钮,会生成一个预览二维码,其他人扫这个码就能进入真机调试版的小程序,但预览码有效期比较短(一般几分钟),适合快速验证;第二种是点击“上传”按钮,把代码版本上传到微信公众平台,然后在后台“管理-版本管理”里把这个版本设为“体验版”,生成体验版的二维码和链接,体验版的有效期比较长,适合发给一批测试用户使用。
体验版比预览版稳很多,因为预览版每次打开都需要重新编译、加载,体验版更像是正式版的模拟。收集试用反馈的标配做法是:在版本管理页面可以看到每天的访问人数、页面访问次数,但单个用户的详细操作日志看不到;如果想要收集用户点击行为或具体反馈,可以在小程序前端内置一个反馈入口,比如一个悬浮的“意见反馈”按钮,点击后打开一个包含问卷或反馈文本的页面,数据提交到后端。这样就可以拿到真正有价值的试用反馈。我还习惯在体验版里埋一个版本号展示,这样用户反馈问题时直接说“我在xxxx版本遇到的”,问题定位速度直线上升。
4.3 错误码10002的识别与处理
微信小程序里报错10002,不同接口场景下含义差别很大。最常见的出现位置是在订阅消息、模板消息或者登录态相关的接口里,通常提示为系统繁忙、参数错误或者内部错误。处理方式不是死记错误码,而是按照通用排查框架走:先看微信官方API文档中这个接口的错误码表,确认10002对应的官方描述;再核对请求参数是否完整,特别是签名、时间戳timestamp、随机数nonce这些字段,很多10002其实是因为时间戳和服务器时间偏差超过5分钟被判为无效请求导致的;再者检查access_token有没有过期,access_token的有效期是7200秒,没有定期刷新会触发一系列错误码,其中就包括10002。
我自己的实践是,在后端统一封装一个微信API调用的模块,把时间戳校准、access_token的缓存刷新、错误码映射都收拢到一处处理,前端只拿到最终的业务结果,不会看到原始错误码。这样排查问题时只需要看后端日志里的微信原始返回和对应参数,效率提升明显。另外提醒一句,微信接口的调用频率限制也会返回类似10002的类型错误,如果你的服务对同一个接口的调用量短期暴增,先检查一下是不是触发了限流。
5. 审核上架与合规要点
5.1 特殊类目资质与合作协议签署
如果你的小程序要添加AI类目,微信公众平台会有额外的资质要求。比如提供对话机器人、内容生成类功能,需要选择“AI”类目,并提交相关资质文件。实际操作中,很多团队并不是自己训练大模型,而是接第三方的AI接口(例如文本生成、图像生成的云服务),此时就需要签订“合作协议”或者“技术接入协议”,协议主体是小程序运营方和AI服务提供方,协议内容要能证明双方存在真实的合作关系,并且明确数据安全责任、内容安全责任。
经验之谈:审核材料里最容易被驳回的点是协议里没有体现小程序的具体名称和具体功能场景。签协议的时候,一定要把“甲方(小程序运营方)”、“乙方(AI技术服务方)”、合作内容包括哪些接口、服务期限、安全责任条款写清楚。盖章越完整越好,最好用彩色扫描件。如果签约的第三方本身没有相关ICP备案或者没有可查的资质,审核大概率会被打回来,所以选AI服务提供商的时候先确认他们的资质是否齐全,别等提交审核才发现问题。
5.2 安全与隐私保护实践
关于防截屏的话题,微信小程序目前并没有提供一个全局的官方防截屏API,iOS系统的防截屏能力原生App能用到,但小程序里暂时调不了系统级的防截屏开关。所以我在做敏感信息类小程序(比如包含合同内容、隐私数据展示的功能)时,安全策略分为三层:第一层是敏感数据展示时使用自定义渲染,尽量不用原生文本展示,比如把关键数字拆成多个元素再拼装,这样截图后不能直接被复制;第二层是增加水印,页面背景铺一层包含用户手机号或用户ID的半透明水印文字,即使截图流传出去也能追溯源头;第三层是禁止页面长按识别和保存图片,对需要保护的图片内容使用canvas绘制而不是直接image标签展示,因为canvas内容无法被系统相册直接保存。安卓端可以尝试监听截屏广播做出提醒,但iOS小程序环境下方案有限。
隐私保护方面,现在微信对用户隐私的管控越来越严。小程序在收集用户手机号、位置、相册信息之前,都必须使用官方隐私协议接口wx.requirePrivacyAuthorize,并且在小程序后台的“用户隐私保护指引”中如实声明收集的信息类型和用途。未声明就调用相关接口会直接报错,这个我已经在项目里碰到过好几回了。建议把隐私指引的更新当成版本发布的前置步骤,和审核材料一起准备,否则提交审核会被驳回。
5.3 小程序名称与账号管理
一个微信账号名下可能会关联多个小程序和公众号,时间长了难免有一堆旧项目需要清理。在小程序后台的“设置-基本设置-名称”里可以修改小程序名称,不过每年只允许修改两次,修改的时候要先去公众平台检测名称是否可用。如果要彻底删除一个不再使用的小程序,需要在小程序后台“设置-基本设置”最底部找到“注销小程序”入口,注销操作有一段时间的冻结期,期间不可操作其他功能,期满后账号才彻底释放。这里要提醒一下:注销前一定要确认小程序没有绑定的商户号、没有未结算的微信支付款项,否则注销会失败或者产生资金问题。
对于“微信登录小程序有好几个名字怎么删除”这类问题,核心是分清场景:如果指的是同一个微信账号下关联了多个小程序,那需要到公众平台“账号中心”里查看关联账号列表,把不用的账号解绑或注销;如果指的是在小程序内部登录页出现了多个历史登录身份,那实际上是微信的“授权登录记录”,通过微信“设置-个人信息与权限-授权管理”里可以撤销对应小程序的授权记录。两种场景处理方式完全不同,不要搞混。
6. 综合项目实战要点
6.1 校园食堂订餐系统的模块设计
基于小程序的校园食堂订餐系统,是很多计算机专业学生做毕业设计的高频选题,也是我刚入行时接过的一个实战项目类型。核心模块划分是:用户端(学生)、商户端(食堂窗口)、管理端(食堂管理员/系统管理员)三端联动。用户端功能包括菜品浏览、购物车、下单结算、订单跟踪、历史订单;商户端要接单、出餐、设置菜品库存和下架;管理端要管理食堂、窗口、商户账号、营业额报表。
从技术实现的角度,需要特别关注的是就餐高峰期的并发处理。校园食堂在午饭晚饭时段流量集中,用户同时下单和支付,数据库的订单表容易成为瓶颈。当时我用了很简单的方案:订单表设计好索引、下单操作使用事务保证库存扣减一致性、支付回调接口做幂等处理。为什么强调幂等?因为微信支付回调在极端情况下可能会重复通知,如果同一支付通知被处理两次,就会生成重复订单或者重复扣减库存。解决思路是在订单表中存一个单调递增的支付流水号,处理回调时先检查流水号是否已存在,存在则直接返回成功,不再重复处理。
6.2 家政服务系统与社区团购的程序结构
基于微信小程序的家政服务系统,这类项目的核心不是技术难点,而是业务流程闭环。用户端需要服务分类(保洁、月嫂、家电维修等),每个服务有对应的价格标准、服务时长和预约时段;下单后平台派单给家政人员(或用户自己选人),家政人员端要有接单、完成服务、上传服务凭证的入口;管理后台要能查看订单状态流转、用户评价、结算数据。程序结构上,我习惯用状态机管理订单状态:待支付、待指派、已指派、服务中、已完成、已取消、退款中。每个状态的流转条件在前端和后端都要校验,前端校验保证用户体验,后端校验保证数据安全。
社区团购系统几个关键点:团长端和小程序用户端的数据隔离、拼团的成团条件和自动退款逻辑、自提点管理。拼团逻辑是社区团购最核心的机制,成团人数在后台可配置,到截止时间未成团则自动触发退款。技术细节上,使用小程序的订阅消息结合模板来给用户推送“成团成功”、“订单到达自提点”的通知也很关键。如果还需要集成地图能力,可以考虑接入天地图这类合规地图服务,在小程序里通过web-view或API集成实现自提点的地图展示和导航。
6.3 项目脚手架的方向
如果看完了这篇笔记,你正打算启动一个新的小程序项目,建议先花半小时搭好项目脚手架:确定框架(原生或uni-app),把目录结构拆好(页面、组件、utils、api),设计好全局状态管理方案,封装好请求库和错误处理。这一套东西看起来不起眼,但后面每个功能开发时都会省下大量时间。我自己的小项目模板已经是第二版了,从一开始的文件夹乱划分到现在按模块划分页面、按业务拆分API文件,开发效率提升非常明显。
最后分享一个我个人的习惯。我每次新起一个项目,都会把所有第三方依赖(包括UI库、图表库、工具库)列一个清单,标清楚它们用在哪个页面、体积多大、有没有替代方案。这个习惯帮助我在体积超限、依赖冲突这类问题上少踩了很多坑。另外,保持看官方文档的习惯,微信小程序API更新速度不算快,但每次更新都可能有影响现有功能的变化——比如隐私协议、登录态策略,都是官方文档先改,再过一段时间社区里才会有反馈。跟着官方文档走,永远比听二手消息靠谱。