尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

uniapp+vue开发微信小程序实战:校友合租平台从0到1全记录

uniapp+vue开发微信小程序实战:校友合租平台从0到1全记录 做校友合租平台这个项目最早是校友会那边找我帮忙说要给毕业校友弄一个房源合租的信息平台。一开始我以为就是个简单的信息发布页面结果越做越发现这个项目的坑比想象中多得多——既要照顾校友端的使用习惯又要处理图片、地图、IM这些重交互还要考虑微信小程序这个载体的各种限制。前后折腾了三个月总算把一版能稳定跑的微信小程序 uniapp vue 方案落了地。这篇文章把我整个技术选型、功能拆解、模块实现和踩坑过程都梳理了一遍希望对正在做同类项目的朋友有帮助。1. 为什么这个项目要绑死uniappvue技术选型背后的现实考量1.1 给非原生技术团队找一条低门槛的出路我接这个项目的时候后台和前端人手其实非常紧张团队里真正写过原生微信小程序的人不超过一个。如果走原生开发光是一个房源表单页面写下来就要同时维护 WXML、WXSS、JS、JSON 四个文件每个交互细节都要自己跟 setData 打交道开发效率说实话不太乐观。uniapp 的价值就在于它把微信小程序的底层细节封装了一层写代码的体验更接近传统的 Vue 开发——模板、样式、逻辑都在单文件组件里心智负担小很多。对于有过 Vue 经验的人来说基本不需要额外学习成本就能上手。这也是我最后选定 uniapp 的核心原因不是因为它功能最全而是团队的学习曲线最平滑。1.2 uniapp到底解决了什么问题uniapp 是一个跨端框架编译器会把你的 Vue 代码编译成微信小程序、H5、App 等多个平台的目标代码。它解决的第一个大问题是平台差异的抹平比如导航栏、页面路由、生命周期这些在 uniapp 里都是一套统一 API。第二个大问题是组件生态uniapp 的插件市场里有很多现成的轮子比如地区选择器、图片裁剪、富文本解析等等直接安装就能用省去了很多重复造轮子的时间。我在做校友合租平台的时候光是从插件市场拿的现成组件就覆盖了滑块验证、身份证识别提示、房屋朝向选择等七八个场景。第三个大问题是调试体验。HBuilderX 里写代码可以直接在浏览器里跑 H5 版本做快速预览也可以在微信开发者工具里跑小程序版本。一些纯前端的逻辑比如表单校验、数据处理在浏览器里调试比在微信开发者工具里调试舒服得多。1.3 vue2还是vue3直接选vue3的理由和代价这个项目启动的时候vue2 在 uniapp 里还算主流但 vue3 的 Composition API 写法确实更符合这个项目对状态管理的需求。合租平台最核心的状态是“当前用户的筛选条件”和“房源列表”用 setup 语法配合 reactive、toRefs 来管理代码可以组织得比 Options API 清晰很多。代价也很明显vue3 版本下一些小程序的特殊钩子比如 onShow、onHide 这些页面生命周期需要从 dcloudio/uni-app 里单独引入和 vue2 里直接在配置项里写 onShow 的体验不一样需要一段时间适应。另外部分第三方插件市场里的组件在 vue3 版本下会出现兼容问题选型前一定要看插件的支持标记。2. 校友合租平台的核心业务拆解从需求到功能落地的设计过程2.1 校友场景和普通租房App的差别在哪里校友房屋合租平台表面上是个租房信息平台但校友身份这个预设条件让产品逻辑和市面上通用的租房软件有本质区别。普通租房平台的信任基础是平台背书需要通过实名认证、营业执照审核这些手段来筛选信息校友平台不一样它的信任基础是“校友”这个共同身份。所以产品的第一个核心模块应该是校友身份认证比如接入校友会的会员数据库或者通过学号、院系、入学年份等信息做人工核验。有了这个信任基础支付宝转账押金、房间转租、合租室友匹配这类高信任需求才能够在平台上跑起来。这也是校友合租平台区别于普通租房App最核心的产品逻辑。2.2 功能地图四条主线贯穿整个平台我把整个平台拆成四条功能主线第一条是房源发布。校友可以发布整套房源也可以发布单间合租信息。发布表单包含小区名称、户型、面积、价格、付款方式、可入住时间、房屋描述、图片最多九张等字段。为了控制垃圾信息还加了手机号验证和发布审核机制。第二条是房源检索。首页有搜索框支持按校区分区、价格区间、户型、合租类型整租、单间、找室友做筛选。检索结果按发布时间倒序排列新发布的房源靠前。第三条是合租匹配。这是我比较满意的一个功能。校友发布房源时可以标注“寻找室友”填写期望室友的性别、作息习惯、是否抽烟、宠物接受度等信息。系统会基于这些标签做自动匹配在有合适的人选时通过微信订阅消息提醒。第四条是站内沟通。考虑到校友之间可能直接需要联系看房我接入了一个轻量级的即时通讯方案。因为项目预算有限没有用声网、环信这些专业的IM服务而是用了即时通讯IM的免费额度搭配云开发数据库的方案可以满足基础的文本消息发送。2.3 数据模型设计一张表把所有关键信息串起来这个项目涉及的核心数据表有用户表、房源表、收藏表、聊天记录表、订阅消息记录表。房源表是整个系统最关键的表字段设计基本上决定了后续所有功能的实现难度。我最初设计房源表的时候有一个字段走了弯路——地址字段直接存了字符串“xx小区xx栋xx室”后来做地图选点功能的时候才发现字符串地址难以做经纬度转换每次都要调第三方API做正向解析。正确的做法是出地理位置信息经度、纬度、结构化地址三个字段分开存。这样既要能显示文字地址又要能调起地图导航。房间信息还涉及到一个细节合租房源和整租房源的字段不一致。整租需要阳台、客厅、厨房这些公共空间的描述合租则需要室友信息、男女要求这些字段。刚开始我把它们塞在一张表里结果查询逻辑越来越乱。后来干脆拆成 houser完整房源记录和 room房间单元记录两张表上面的整租/合租共用基本信息下面的 room 表单独维护每一间房间的差异化信息查询效率也上去了。3. 从HBuilderX到微信开发者工具初始化与工程结构搭建3.1 创建项目和manifest配置的完整过程项目的起步是 HBuilderX 创建 uni-app 项目选 vue3 模板。创建完之后第一步就是配置 manifest.json 里的小程序相关项这一步很多人会直接跳过导致后面发布时踩一堆坑。manifest.json 里小程序配置部分除了最基础的应用名称这部分会显示在小程序后台和 AppID 之外有三个地方容易被忽略第一个是“基础库最低版本”设置。这个值决定了你的小程序能够运行的最低微信基础库版本。我开发的时候默认设置的是 2.6.5结果发现有几个 API 在低版本库上不支持导致部分老手机用户打不开页面。后来我把最低版本调到 2.16.0 才解决了兼容问题。这个调整对于用户量大的小程序是有影响的如果太激进的调高版本会放弃一部分低版本用户如果调太低又会限制自己使用新 API。建议以微信官方目前主流支持的基础库版本为准。第二个是“权限设置”。小程序如果要用到位置功能必须在 manifest.json 里声明位置相关的权限接口否则调用 uni.getLocation 的时候会直接报错。这个位置权限不是申请弹窗而是在代码层先声明了才能调用。第三个是“分享设置”。如果要做自定义分享功能需要在 manifest.json 的微信小程序配置里开启分享相关设置否则即使页面上写了 onShareAppMessage 生命周期分享按钮也可能不生效。3.2 目录结构设计页面太多导致的教训项目初期我按照 uniapp 默认的目录结构来组织直接把所有页面都丢在 pages 目录下。结果页面一多目录里文件名全是 p1、p2 这种毫无规则的名字找文件找一个小时。后来我重新整理了目录结构把每个功能模块的页面单独放一个文件夹src/ pages/ home/ # 首页相关首页、搜索页、筛选页 publish/ # 发布相关发布表单、发布成功页、我的房源 detail/ # 房源详情详情页、预约看房、收藏列表 message/ # 沟通相关会话列表、聊天页 profile/ # 个人中心个人主页、认证页、设置 components/ # 公共组件 house-card/ # 房源卡片组件 filter-bar/ # 筛选栏组件 empty-state/ # 空状态组件 ... utils/ request.js # 请求封装 auth.js # 登录态管理 format.js # 格式化工具 api/ house.js # 房源相关接口 user.js # 用户相关接口 message.js # 消息接口 store/ # Pinia 状态管理 ...这个过程中最深刻的教训是页面之间的跳转参数尽量通过页面URL参数传递而不是用全局变量。微信小程序的全局变量在冷启动之后可能被清空导致页面拿到空数据这个在开发期间排了好久的错才意识到。3.3 pages.json与tabBar配置导航栏的设计要点pages.json 是 uniapp 里配置页面路由、导航栏样式、底部tabBar的配置文件。校友合租平台的底部导航我设置了三个入口首页、发布、我的。这里有个需要注意的点tabBar 的页面路径必须配置在 pages.json 的 tabBar.list 里而且这些页面不能通过 uni.navigateTo 跳转只能通过 uni.switchTab 切换。如果你在发布成功之后想跳回首页不能用 navigateBack 或者 redirectTo必须用 uni.switchTab。tabBar 的图标建议用 81px * 81px 的 PNG 图大小要控制在 40KB 以内不然小程序真机预览的时候图标会显示不出来。这个尺寸问题我一开始没注意真机上首页图标直接消失排查了半天。4. 房源发布模块表单、图片上传与数据校验的细节实现4.1 发布表单页面的两个核心痛点房源发布是整个平台使用频率最高的功能之一也是用户跳出率最高的页面。一个不太合理的发布表单用户填到一半可能就放弃了。常见的问题是字段太多、没有保存草稿、输入错误提示不到位、图片上传失败没有重试机制。我在设计这个页面时把字段分成了两个 step。第一步是房屋基本信息小区名称、户型、面积、价格、付款方式。第二步是合租信息合租类型、室友描述、期望室友要求、房屋照片。分两步的好处是降低用户的心理负担每步只需要面对五个以内的输入项。表单校验方面我用了内置的 uni-forms 组件配合 rules 校验规则。这里有一个坑uni-forms 的 rules 里每个字段的 name 必须和表单数据里的 key 一致否则校验不生效。我一开始没注意到这个细节导致价格必填校验一直没触发用户留空也能提交。4.2 图片上传方案选uni.uploadFile还是云存储房屋图片上传可以选择 uni.uploadFile 直接把图片传到自己的服务器也可以选择上传到云开发的云存储再拿临时链接。考虑到服务器带宽有限我选择了腾讯云 COS 做对象存储。流程是小程序端选择图片 - 将图片转成临时路径 - 传给后端 - 后端向 COS 发送预签名 URL - 小程序端拿这个 URL 把图片直传到 COS - 上传完成回调后端记录图片地址。用预签名 URL 直传的好处是图片流量不经过自己的应用服务器服务器不会被大文件拖垮。坏处是流程链路比较长之前没做过的话会有点绕。动手之前建议先了解一个概念COS 的预签名 URL 其实就是把上传凭证在服务端算好给客户端用。这样你服务器上不用维护 COS 的密钥安全性也更好。具体实现的时候要注意 uni.chooseImage 返回的 tempFilePaths 是本地临时文件路径。直接把这个路径传给后端生成预签名 URL 是没有意义的因为后端拿不到这个文件需要先上传到 COS然后再拿 COS 上返回的 URL 作为最终展示的图片地址。所以图片上传的流程是chooseImage - 把临时文件传给 COS通过预签名URL的方式- COS 返回 fileKey - 后端确认文件存在后把 fileKey 存到房源记录里。多图上传的时候还要处理上传进度和失败的重新上传。我用 uni.uploadFile 的 onProgressUpdate 回调更新进度条失败的图片在九宫格组件里标记“重新上传”按钮避免用户因为一张图传不上去就要重新填整个表单。4.3 发布接口的幂等性与防重复提交发布表单的提交按钮双击会导致重复发布生成两条一样的房源。这个是我上线第一天就被人抓到的问题。解决办法是在前端做一个发布锁点击提交按钮后立即把按钮置为 disabled 状态同时发起请求等接口返回之后再恢复可点击状态。后端也需要在数据库层做唯一约束比如基于同样的 phone house_id create_time 组合做重复记录检测。后端接口还应该做幂等性设计因为小程序端的请求在网络异常时可能会自动重试。最稳妥的方案是前端生成一个 request_idUUID提交时带上后端根据这个 request_id 做去重。5. 房源检索与合租匹配从列表页到推荐算法的落地细节5.1 首页信息流与搜索筛选交互设计首页的房源列表是这个项目的门面。我在实现首页信息流的时候没有直接用简单的列表组件而是用 scroll-view 配合分页加载实现上拉加载更多。这里有一个微信小程序的性能优化点不建议用 onReachBottom 做加载更多因为它在某些安卓机型上触发不灵敏用 scroll-view 自带的 scrolltolower 事件更可靠。搜索筛选部分我做了两条路径普通搜索和高级筛选。普通搜索就是顶部搜索框支持小区名称模糊搜索。高级筛选是一个底部弹层支持地区按校区划分、价格区间500以下、500-1000、1000-2000、2000以上、户型一室一厅、两室一厅、单间、合租类型整套、合租四个维度。筛选条件的传参设计这里有一个容易忽略的细节当用户离开筛选页再回来时筛选条件默认应该重置成上一次的状态而不是全部清空。实现方式是把筛选条件对象存进 Pinia页面离开时保留回到首页时读取。5.2 位置信息与地图找房我发现很多校友找房的第一诉求是“离学校近”。所以首页除了常规的信息流之外还做了一个地图视图用户可以看到学校周边几公里范围内的房源分布。实现上用到了 uni.getLocation 获取用户当前位置需要在 manifest 里配置好位置权限然后通过 uni.openLocation 打开地图查看某个房源的准确位置也可以用 map 组件把多个房源点展示在一张地图上。地图找房这里有一个数据层的注意点因为系统返回的是用户任意坐标和房源坐标的距离所以经纬度的存储精度很重要。我直接用 DOUBLE 类型存经纬度但实际测试发现有些边界坐标会出现精度误差导致距离计算漂移几百米。后来改成 DECIMAL(10, 7) 类型存经纬度问题就解决了。5.3 合租匹配的简单可行算法匹配算法我没用太复杂的东西核心是一个打分公式根据用户填的期望室友条件和房主填的接受室友条件做匹配度计算。维度包括性别同性别优先、作息早睡早起/晚睡晚起/不规律、抽烟接受/不接受、宠物接受/不接受四项。每一项的权重可以调整我暂时设定为性别权重 0.3作息权重 0.3抽烟权重 0.2宠物权重 0.2。总匹配度 各项得分 x 权重的累加。比如一个用户期望室友是“男、早睡、不抽烟、接受宠物”某个房主写的是“男、晚睡、不抽烟、不接受宠物”那么性别匹配1分 x 0.3、作息不匹配0分 x 0.3、抽烟匹配1分 x 0.2、宠物不匹配0分 x 0.2总匹配度就是 0.5。为了不误导用户匹配度会以“60% 匹配”这种形式展示同时列出匹配和不匹配的具体项。匹配到高分70%以上的用户会收到一条订阅消息提醒引导对方去查看房源详情。这个算法的实现放在后端。每次房源状态变更后端会异步跑一次匹配任务把匹配结果记录到 match_list 表再通过订阅消息发送通知。实时性要求不高用简单的定时任务就够了。6. 微信小程序环境里的适配与排坑真实遇到的问题清单6.1 切换页面时底部导航闪烁问题这个问题折磨了我快一周。现象是在某些安卓机型上从首页 tab 切换到发布 tab 时底部导航条会闪一下然后才正常显示。排查过程第一步我先怀疑是 tabBar 图标的尺寸问题。把图标从 60px 换到 81px重新生成问题依然存在。第二步我怀疑是页面切换动画导致的。在 pages.json 全局配置里把 animationType 改成 none结果没用。第三步我去社区里翻了很久最后在一个很老的帖子里看到这是 HBuilderX 2.x 时代的一个老 bug跟页面栈的销毁重建有关。升级到 HBuilderX 3.x 之后问题就消失了。所以如果你也遇到类似的情况第一件事先检查自己的 HBuilderX 是不是最新版本。6.2 webview返回方式跟常规页面返回不一样校友合租平台里有一个模块是用 webview 嵌入的——学校周边的全景看房H5页面。页面上有一个“返回列表”按钮我用的是 uni.navigateBack结果发现完全没有反应连报错都没有。后来我才明白webview 页面本身是天然页面栈里的一个页面但在 webview 内部导航过之后返回逻辑会跟页面栈脱节。正确的处理方式是在 webview 页面上监听 message 事件让 H5 页面通过 postMessage 通知小程序端执行 navigateBack 操作。具体的实现方式是在 H5 页面里的返回按钮点击事件中调用wx.miniProgram.postMessage({ data: { action: back } })小程序端在 webview 页面里监听bindmessageonMessage收到 action 为 back 的消息后执行uni.navigateBack()。6.3 uniapp生命周期与页面返回的数据刷新问题分享这个项目的过程中最容易被忽视的是 uniapp 页面生命周期在小程序里的行为差异。比如 onLoad 只在页面首次加载时触发onShow 每次从后台切回前台或从其他页面返回时都会触发。所以实现“从详情页返回列表页时刷新列表”的逻辑应该在 onShow 里写刷新函数而不是 onLoad。还有一个很隐蔽的坑当你在页面 A 提交完数据通过 uni.redirectTo 跳转到页面 B 后从 B 返回 A 时A 会重新触发 onLoad 吗不会redirectTo 会关闭当前页面所以 A 的 onLoad 不会重新执行。如果 A 的数据没有存到全局返回时看到的还是旧的。我在做发布成功后返回首页的逻辑时就被这个坑过一次。正确的做法是发布成功之后用 uni.switchTab 跳到首页同时修改 Pinia 里的一个变量 isDataChanged true首页在 onShow 里读到这个变量就重新拉取列表数据。6.4 基础库版本设置与API兼容性微信小程序的 API 是不断迭代的新 API 只在新基础库版本里可用。比如 uni.authorize 里新增的接口类型在旧版基础库里根本不认识调用会直接报错。所以当你的小程序发布之后后台统计里会看到某个机型或者某些版本的用户报错通常都是基础库版本太低导致的。处理方式在 manifest.json 里设置合理的 libVersion。在代码里通过 uni.getSystemInfoSync().version 获取用户当前基础库版本。对低版本用户做降级处理比如用条件编译写两套逻辑。6.5 扫码功能在真机上不清晰的排查过程热词里有一个“uniapp扫码不清晰”这个我也踩过。用 uni.scanCode 调起微信扫码在部分安卓机特别是小米机型上扫码取景画面很糊二维码半天扫不出来。排查下来有两个原因一是摄像头自动对焦没有触发需要在 uni.scanCode 调用前先调一次 uni.getCameraInfo 唤醒相机二是如果页面上有自定义样式覆盖或页面的 opacity 不为 1会导致预览显示异常。最后把页面样式复位到默认状态同时减少页面层级问题基本就解决了。7. 从HBuilderX到上线微信小程序发行打包全流程7.1 发行前的检查清单每次打包前我都会按下面的清单过一遍能省下不少麻烦manifest.json 里的 AppID 确认无误如果用的是测试号真机预览和上传代码都会失败。基础库最低版本已经设置且所有用到的 API 都兼容该版本。微信开发者工具里的“全方位调试”真机调试先在真机跑一遍重点测图片上传、位置获取、支付如果接入了。检查代码里有没有遗留的 console.log 影响性能尤其是循环里的打印。检查图片资源是否全部在本地如果引用了外链图片要在小程序后台配置 downloadFile 合法域名。检查有没有用到 webview如果用了要在业务域名里配置合法域名并且该域名需要ICP备案。7.2 HBuilderX发行到微信开发者工具的完整步骤HBuilderX 里发行微信小程序版本的步骤特别简单菜单栏点击 发行 - 小程序-微信选择发行模式。HBuilderX 会自动编译并生成 dist/dev/mp-weixin 目录的代码。打开微信开发者工具选择“导入项目”目录选择 dist/dev/mp-weixin。填上小程序的 AppID确定即可。这里有一个坑如果 HBuilderX 的“发行”操作提示找不到 AppID通常是因为 manifest.json 里没填对或者你用的是个人版小程序账号没有对应权限。检查一下 manifest.json 里 mp-weixin 配置块的 appid 字段。7.3 版本迭代与小程序审核注意事项小程序每次发版都需要微信后台审核审核周期从几小时到一两天不等。为了避免不必要的返工我有几条经验审核时不要把核心功能藏起来需要保证审核人员能顺利走通发布-浏览-联系看房的完整流程。如果发布了房源需要管理员后台审核审核人员发布的信息可能无法立刻展示这样容易被拒。比较好的处理方式是在测试环境开放免审核通道或者提供一个预置测试账号。涉及收费功能押金、租金支付的模块在审核时尽量先展示为“线下洽谈”等审核通过后再切换到线上支付否则需要申请微信支付的小程序专属商户号审核周期更长。小程序后台的管理规则里有规定涉及用户隐私信息手机号、位置的采集必须有对应的隐私政策说明页并且在小程序后台“用户隐私保护指引”里如实填写。这个不填的话第一次提审大概率会被打回。7.4 uniapp离线打包与上架安卓应用市场的补充方案虽然这版项目主要用于微信小程序但用 uniapp 还有一个天然优势——以后如果要发 App 版同一套代码可以直接打包成 Android 和 iOS 应用。离线打包在 HBuilderX 里做不了你需要先把代码在 HBuilderX 里发行成“本地打包资源”然后在 Android Studio 里使用 uni-app 官方提供的离线打包 SDK 工程来集成。离线打包的难点在于 uTS 插件的配置以及原生工程的包名、签名文件、权限声明一定要在 Android 的 AndroidManifest.xml 里配置好。这里我不详细展开 App 打包因为项目目前还是以小程序为主但如果你有这个需求提前了解一下 5App 的离线打包流程会省很多事。8. 项目上线之后的运维与迭代建议8.1 数据统计与埋点方案合租平台上线之后最重要的就是数据。我在项目里接入了 uni-stat 做基础统计可以看到访问量、新用户数、页面停留时长这些基础指标。不过 uni-stat 获取不到更精细的路径转化和漏斗分析所以后期我建议接一下微信官方的数据分析在小程序后台开通“数据助手”会自动输出页面访问、分享次数、新用户来源等数据。这里有一个优化点在做按钮级别的埋点时如果每个按钮的事件回调里手动写埋点代码会非常繁琐且容易漏。我后来封装了一个 track 函数在根组件上挂一个 mixin自动监听所有带>
返回列表