uniapp开发跨端小程序重点
UniApp 开发小程序端
本文档为纯小程序端专属内容,完整覆盖从项目搭建、核心配置、全量生命周期、条件编译、组件API规范、性能优化到发布上线的全流程,适配UniApp开发小程序的生产级要求。
项目实践
code/all/mp-yswx 微信小程序、钉钉小程序
code/all/dd-v5 企业微信、h5
code/all/yt-digital-resource h5
code/all/yt-straight-a-project h5
一、小程序端项目初始化与核心配置(全量专属详解)
小程序端的所有平台规则、包体积限制、路由权限、原生能力均围绕 manifest.json 与 pages.json 两大配置文件展开,是小程序开发的核心根基,所有配置项直接影响功能可用性、启动性能与审核通过率。
1.1 项目初始化
- 使用HBuilderX创建项目,选择「uni-app项目」,根据技术栈选择Vue2/Vue3模板,推荐使用官方uni-ui模板,小程序端原生兼容性最优。
- 项目创建后,优先完成
manifest.json小程序平台配置与pages.json路由规则配置,否则无法正常运行到微信开发者工具。
1.2 manifest.json 小程序端全量核心配置
该文件为小程序应用级配置,直接关联微信公众平台的AppID、编译规则、权限配置,核心配置项全量详解如下:
1.2.1 基础配置
| 配置项 | 核心说明 | 硬性规则 |
|---|---|---|
| 应用名称 | 小程序对外显示名称,需与微信公众平台注册名称一致 | 控制在4-16个字符,避免特殊字符、违规词汇 |
| 应用版本名称 | 对外显示的版本号,如1.0.0 |
遵循语义化版本规范,每次上传代码必须递增,与微信公众平台版本管理对应 |
| 应用版本号 | 对内整数版本号,如1、2、3 |
每次上传代码必须严格递增,用于版本迭代区分 |
| 微信小程序AppID | 小程序唯一身份标识 | 必须从微信公众平台「开发管理-开发设置」中获取,未填写无法真机调试、上传代码 |
1.2.2 微信小程序专属编译配置
| 配置项 | 核心作用 | 最佳实践 |
|---|---|---|
| ES6转ES5 | 开启后将ES6+语法转为ES5,兼容低版本微信客户端 | 强制开启,否则低版本基础库会出现语法报错 |
| 增强编译 | 支持async/await、可选链等新语法,扩展Polyfill | 强制开启,解决新语法兼容问题 |
| 上传代码时自动压缩 | 自动压缩混淆代码、图片、JSON文件,减小包体积 | 强制开启,是包体积瘦身的基础配置 |
| 上传时自动清理console.log | 剔除调试日志,减小包体积,避免泄露敏感信息 | 正式发布时强制开启,开发环境可关闭 |
| 忽略未使用的资源 | 自动剔除未引用的静态资源、组件、代码,减小包体积 | 强制开启,解决冗余资源占用包体积问题 |
| 代码按需注入 | 对应微信小程序lazyCodeLoading配置 |
开启并设置为requiredComponents,大幅提升小程序启动速度 |
| 调试时不校验合法域名、web-view业务域名、TLS版本 | 开发环境关闭域名校验 | 开发时开启,正式发布必须关闭,且所有域名必须在微信公众平台配置白名单 |
1.2.3 多小程序平台兼容配置
如需兼容支付宝、抖音、百度等小程序平台,需在对应平台配置栏填写对应平台的AppID,开启对应平台的编译配置,后续通过条件编译处理平台差异。
1.3 pages.json 小程序端全量核心配置
pages.json 是小程序的全局路由与窗口配置文件,控制页面路由、分包规则、导航栏、tabBar、下拉刷新等核心能力,所有页面必须在此注册,否则无法访问,小程序端专属规则全量详解如下:
1.3.1 全局配置 globalStyle
控制所有页面的默认窗口表现,页面级配置优先级高于全局配置,核心配置项:
| 配置项 | 核心作用 | 小程序端专属规则 |
|---|---|---|
navigationBarBackgroundColor |
导航栏背景色 | 仅支持十六进制颜色值,不支持rgba、渐变、英文颜色名 |
navigationBarTextStyle |
导航栏标题文字颜色 | 仅支持black/white两个值,无其他选项 |
navigationBarTitleText |
全局默认导航栏标题 | 页面级配置会覆盖该值 |
navigationStyle |
导航栏样式 | 设置为custom可隐藏原生导航栏,实现自定义导航栏,仅微信基础库2.4.3+支持 |
enablePullDownRefresh |
全局开启下拉刷新 | 默认关闭,开启后所有页面均可触发下拉刷新,推荐页面级单独配置 |
backgroundColor |
窗口背景色(下拉露底区域) | 仅支持十六进制颜色值 |
backgroundTextStyle |
下拉刷新loading样式 | 仅支持dark/light两个值 |
onReachBottomDistance |
页面上拉触底事件触发距离 | 单位px,默认50px,数值越小触发越早 |
1.3.2 页面路由配置 pages
数组格式,每个元素对应一个页面,数组第一项为小程序启动首页,单页面配置结构如下:
1 | |
小程序端硬性规则:页面路径无需写
.vue后缀,必须放在pages目录下(分包页面除外),路径大小写敏感,错误路径会导致页面无法访问。
1.3.3 分包加载配置 subPackages(小程序核心硬性要求)
微信小程序官方硬性限制:主包(含tabBar页面)体积≤2MB,主包+所有分包总大小≤20MB,超过限制无法上传代码、提交审核,必须通过分包拆分非核心页面,是小程序开发的重中之重。
核心配置结构
1 | |
核心规则详解
root:分包根目录名称,不能与其他分包重名,不能嵌套分包;分包内的所有页面、资源必须放在该根目录下。pages:分包内的页面路径,规则与主包pages一致。independent:是否为独立分包,设置为true时,该分包不依赖主包,可独立启动,无需下载主包即可打开,适合活动页、推广页、H5跳转落地页;独立分包不能使用主包的公共组件、公共资源、全局变量,需单独封装。- 硬性规则:tabBar页面必须放在主包内,不能放入分包;主包只能引用主包内的资源,分包可引用主包和自身分包内的资源,分包之间不能互相引用资源。
1.3.4 分包预加载配置 preloadRule
用于配置进入某个页面时,自动预下载指定分包,解决分包页面打开时的加载延迟,提升用户体验,配置结构如下:
1 | |
| 配置项 | 核心说明 |
|---|---|
| key值 | 触发预加载的页面路径,必须是主包内已注册的页面 |
network |
预加载的网络环境,可选wifi(仅wifi环境预加载)/all(所有网络环境均预加载) |
packages |
要预加载的分包root名称数组,可同时预加载多个分包 |
1.3.5 tabBar底部导航配置
小程序端tabBar硬性规则:最少2个、最多5个tab;tab对应的页面必须在主包pages数组中,不能放在分包;tabBar页面切换时,仅触发onShow/onHide,不会触发onLoad/onUnload。
pages.json中完整配置结构:
1 | |
| 配置项 | 小程序端专属规则 |
|---|---|
color |
tab默认文字颜色,仅支持十六进制颜色值 |
selectedColor |
tab选中时的文字颜色,仅支持十六进制颜色值 |
borderStyle |
tabBar上边框颜色,仅支持black/white两个值 |
position |
tabBar位置,仅支持bottom/top,设置为top时不显示图标 |
iconPath/selectedIconPath |
图标路径,仅支持本地图片,不支持网络图片;图片大小限制40KB,尺寸建议81px*81px |
1.3.6 小程序端专属权限与能力配置
1 | |
二、小程序端全量生命周期体系(100%全覆盖)
小程序端生命周期分为应用生命周期、页面生命周期、组件生命周期三大类,每个钩子的触发时机、接收参数、使用场景、小程序专属注意事项全量详解如下,完全适配UniApp开发规范。
2.1 应用生命周期(仅在App.vue中生效,全局唯一)
控制整个小程序的启动、前后台切换、全局错误捕获,全局仅在App.vue中生效,是小程序全局初始化的唯一入口。
| 生命周期钩子 | 触发时机 | 接收参数 | 核心使用场景 | 小程序端专属注意事项 |
|---|---|---|---|---|
onLaunch |
小程序冷启动初始化完成时触发,全局仅触发1次 | options对象,核心字段:- scene:微信小程序场景值(如1001=主界面下拉进入、1007=分享卡片进入、1011=扫码进入)- path:启动页面路径- query:启动页面参数- shareTicket:群分享票据,用于获取群分享信息- referrerInfo:来源小程序/公众号的AppID |
1. 全局初始化:检查用户登录状态、token有效性 2. 全局配置挂载:接口域名、全局常量、公共方法 3. 处理扫码、分享、外部链接进入的启动逻辑 4. 注册全局错误监听、小程序更新监听 5. 统计小程序启动次数、渠道来源 |
1. 仅冷启动触发,热启动(后台切回)不触发 2. 此时页面未渲染,不能操作DOM、不能调用页面级方法 3. 小程序被销毁后重新打开才会再次触发 4. 禁止写入高耗时同步逻辑,否则会导致小程序启动白屏、卡顿 |
onShow |
小程序启动,或从后台切入前台显示时触发,每次切前台都会触发 | 同onLaunch的options参数 |
1. 刷新用户登录状态、token续期 2. 重启暂停的音频/视频播放 3. 同步全局用户信息、刷新实时数据 4. 检查小程序版本更新 5. 统计小程序前台停留时长 |
1. 冷启动时,在onLaunch之后触发2. 热启动仅触发 onShow,不触发onLaunch3. 锁屏后解锁、从其他App/公众号切回小程序都会触发,触发频率高,禁止写入高耗时同步逻辑 |
onHide |
小程序从前台切入后台时触发(按Home键、切换App/小程序、关闭小程序) | 无参数 | 1. 暂停音频/视频播放,避免后台耗电 2. 保存用户临时操作数据、页面状态 3. 断开非必要的websocket、定位服务 4. 统计小程序后台停留时长 |
1. 微信对小程序后台运行时间有限制,禁止执行耗时过长操作 2. 页面切换不会触发,仅小程序整体进入后台触发 |
onError |
小程序发生脚本错误、API调用失败时触发 | error:错误信息完整字符串 |
1. 全局错误捕获与上报 2. 友好错误提示,避免小程序白屏 3. 记录错误日志,用于线上问题排查 |
1. 同步代码错误会触发,异步Promise reject需额外监听onUnhandledRejection2. 禁止在此钩子内抛出新错误,导致死循环 |
onPageNotFound |
小程序打开的页面路径不存在时触发 | 对象参数,核心字段: - path:无效页面路径- query:页面参数- isEntryPage:是否为启动页 |
1. 页面不存在的兜底跳转,如跳转到首页/404页 2. 无效路径上报,用于修复下线页面的跳转问题 3. 兼容旧版本下线页面的重定向 |
1. 重定向必须使用uni.reLaunch/uni.redirectTo,禁止用uni.navigateTo2. 扫码、外部链接、分享卡片打开无效页面均会触发 |
onUnhandledRejection |
小程序出现未处理的Promise reject时触发 | 对象参数,核心字段: - reason:拒绝原因- promise:对应Promise对象 |
全局捕获异步接口、异步操作的错误,统一上报和友好提示 | 仅微信基础库2.10.0以上版本支持,低版本需做兼容降级 |
onThemeChange |
小程序系统深色/浅色主题切换时触发 | 对象参数,包含theme(dark/light) |
监听系统主题变化,动态切换小程序深色/浅色模式 | 仅微信基础库2.11.0以上版本支持 |
App.vue 完整代码示例(小程序端专属)
1 | |
2.2 页面生命周期(每个页面.vue文件中生效,页面级专属)
控制单个页面的加载、渲染、显示、隐藏、卸载、用户交互,是小程序开发中最常用的生命周期,包含微信小程序专属社交、交互钩子,全量详解如下:
| 生命周期钩子 | 触发时机 | 接收参数 | 核心使用场景 | 小程序端专属注意事项 |
|---|---|---|---|---|
onLoad |
页面加载时触发,每个页面仅触发1次 | options:接收上一页通过URL传递的参数(如/pages/detail?id=123,可通过options.id获取) |
1. 获取页面入参,初始化核心数据 2. 发起页面初始数据接口请求 3. 初始化定时器、事件监听 |
1. 仅触发1次,页面卸载前不会重复触发 2. 页面返回再进入,不会触发 onLoad,仅触发onShow3. 超长参数禁止通过URL传递,改用全局存储/事件总线 4. 此时DOM未渲染,不能获取节点尺寸、操作DOM |
onShow |
页面显示时触发,每次切入前台都会触发(首次加载、返回当前页、小程序切前台) | 无参数 | 1. 刷新页面数据,如详情页返回后刷新列表状态 2. 重启暂停的动画、音频 3. 更新实时数据(倒计时、用户信息) |
1. tabBar页面切换时,仅触发onShow/onHide,不触发onLoad/onUnload2. 触发频率高,禁止写入高耗时同步逻辑 |
onReady |
页面初次渲染完成时触发,每个页面仅触发1次 | 无参数 | 1. 获取DOM节点尺寸、位置信息 2. 初始化canvas、地图、视频等原生组件 3. 执行依赖DOM渲染完成的动画 4. 自定义导航栏场景下,获取微信胶囊按钮位置 |
1. 仅触发1次,在onLoad/onShow之后触发2. 必须配合 this.$nextTick使用,确保节点100%渲染完成3. 小程序端仅在此钩子触发后,才能通过 uni.createSelectorQuery()获取节点信息 |
onHide |
页面隐藏时触发(跳转到下一页、tab切换、小程序切后台) | 无参数 | 1. 暂停动画、定时器、音频播放 2. 保存临时输入内容、页面滚动位置 3. 解绑事件监听,避免内存泄漏 |
页面跳转时,先触发当前页onHide,再触发下一页onLoad |
onUnload |
页面卸载时触发,每个页面仅触发1次 | 无参数 | 1. 销毁所有定时器、延时器 2. 解绑所有事件监听(事件总线、websocket) 3. 销毁canvas、地图、视频等占用内存的组件 4. 取消未完成的接口请求 |
1. 触发场景:uni.redirectTo、uni.navigateBack关闭当前页、uni.reLaunch关闭所有页面2. uni.navigateTo不会触发当前页onUnload,仅触发onHide3. 必须在此清理所有副作用,否则会导致小程序内存泄漏、卡顿、闪退 4. 小程序页面栈最多10层,超出后 navigateTo无法打开新页面 |
onPullDownRefresh |
页面下拉刷新时触发 | 无参数 | 1. 重新请求页面数据,刷新列表 2. 重置页面状态、分页参数 |
1. 必须在pages.json的globalStyle或页面style中配置enablePullDownRefresh: true才能触发2. 刷新完成后必须调用 uni.stopPullDownRefresh()停止刷新动画,否则会一直处于刷新状态3. 自定义导航栏需额外处理下拉刷新的兼容 |
onReachBottom |
页面滚动到底部时触发 | 无参数 | 列表分页加载,触发下一页数据请求 | 1. 触发距离可通过onReachBottomDistance配置,默认50px2. 页面高度不足1屏时不会触发 3. scroll-view的滚动不会触发此钩子,需用scrolltolower事件4. 必须做节流和加载状态锁,避免重复请求 |
onShareAppMessage |
页面右上角「分享给朋友」按钮点击时触发,必须return分享配置对象 | 对象参数,核心字段: - from:触发来源,button=页面内分享按钮触发、menu=右上角菜单触发- target:触发分享的button组件实例- webViewUrl:web-view组件的当前链接 |
1. 自定义分享标题、路径、封面图 2. 统计分享次数、分享渠道 3. 配置分享参数,实现分享裂变 |
1. 只有定义此钩子,右上角菜单才会显示「分享给朋友」按钮 2. 微信已回收分享成功/失败回调,无法监听用户是否真的分享成功 3. 分享路径必须是小程序已注册的页面路径,可携带query参数 4. 分享图片大小限制2MB,比例推荐5:4 |
onShareTimeline |
页面右上角「分享到朋友圈」按钮点击时触发,必须return分享配置对象 | 无参数 | 自定义分享到朋友圈的标题、封面图、查询参数 | 1. 仅微信基础库2.11.0以上版本支持 2. 只有定义此钩子,右上角菜单才会显示「分享到朋友圈」按钮 3. 无法自定义分享路径,仅能通过query传递参数,打开后会进入单页模式 |
onAddToFavorites |
页面右上角「收藏」按钮点击时触发,必须return收藏配置对象 | 对象参数,包含webViewUrl:当前页面链接 |
自定义收藏的标题、封面图、收藏内容、query参数 | 仅微信基础库2.10.0以上版本支持 |
onPageScroll |
页面滚动时实时触发 | 对象参数,包含scrollTop:页面垂直滚动距离,单位px |
1. 滚动时动态修改导航栏透明度、标题样式 2. 控制回到顶部按钮的显示/隐藏 3. 实现滚动动画效果 |
1. 触发频率极高,必须做节流处理(推荐100ms以上) 2. 禁止在此钩子里做频繁的setData操作,会严重占用小程序主线程,导致卡顿、掉帧 |
onTabItemTap |
tabBar页面点击tab按钮时触发 | 对象参数,核心字段: - index:tab序号,从0开始- pagePath:tab对应的页面路径- text:tab的文字 |
1. 点击tab时刷新页面数据 2. 拦截tab点击,如未登录时跳转到登录页 3. 统计tab点击次数 |
1. 仅在tabBar页面中生效,非tabBar页面不触发 2. 点击当前已选中的tab也会触发 |
onResize |
小程序窗口尺寸变化时触发(如横竖屏切换) | 对象参数,包含size:窗口尺寸信息,windowWidth/windowHeight |
适配横竖屏切换,动态修改页面布局 | 仅支持横竖屏切换的页面触发 |
页面生命周期完整代码示例(小程序端专属)
1 | |
2.3 组件生命周期(自定义组件中生效,Vue标准+小程序专属)
小程序端组件生命周期优先遵循Vue标准生命周期,同时兼容微信小程序原生组件的lifetimes生命周期,全量钩子详解如下:
| 生命周期钩子 | 类型 | 触发时机 | 核心使用场景 | 小程序端注意事项 |
|---|---|---|---|---|
beforeCreate |
Vue标准 | 组件实例刚创建,数据观测未初始化 | 极少使用,仅能获取this,无法访问data/methods | 触发时机极早,无法访问组件数据、props |
created |
Vue标准 | 组件实例创建完成,data/methods/props已初始化,DOM未生成 | 1. 发起组件所需数据的接口请求 2. 初始化组件内部状态 3. 注册事件监听 |
此时组件未挂载,不能操作DOM节点、获取组件尺寸 |
beforeMount |
Vue标准 | 组件挂载开始前,模板编译完成 | 极少使用 | 触发在created之后,mounted之前 |
mounted |
Vue标准 | 组件挂载到DOM完成 | 1. 获取组件内DOM节点信息 2. 初始化canvas、动画等依赖DOM的逻辑 |
1. 小程序端mounted触发时,未必能100%获取节点,必须配合this.$nextTick2. v-if控制的组件,每次显示都会重新触发mounted 3. 小程序端必须使用 uni.createSelectorQuery().in(this)才能获取组件内的节点 |
beforeUpdate |
Vue标准 | 组件数据更新,DOM重渲染前触发 | 监听数据变化,获取更新前的DOM状态 | 频繁触发,慎用,避免影响小程序渲染性能 |
updated |
Vue标准 | 组件数据更新,DOM重渲染完成后触发 | 数据更新后,操作更新后的DOM节点 | 禁止在此钩子里修改组件data数据,否则会触发无限更新循环 |
beforeDestroy |
Vue标准 | 组件实例销毁前触发,实例完全可用 | 1. 清理定时器、延时器 2. 解绑事件监听 3. 取消未完成的接口请求 |
必须在此清理所有副作用,避免小程序内存泄漏 |
destroyed |
Vue标准 | 组件实例销毁完成后触发 | 最终清理逻辑,销毁占用内存的对象 | 仅触发1次 |
attached |
小程序专属 | 组件实例进入页面节点树时触发 | 小程序原生组件初始化逻辑,类似created | 1. 必须用#ifdef MP-WEIXIN条件编译包裹2. 必须写在 lifetimes节点内,不能直接写在组件根级别 |
detached |
小程序专属 | 组件实例被移出页面节点树时触发 | 小程序原生组件销毁逻辑,类似beforeDestroy | 同上,必须条件编译包裹 |
ready |
小程序专属 | 组件在视图层布局完成后触发 | 类似mounted,获取DOM节点信息 | 同上,需基础库2.2.3+支持 |
组件生命周期完整代码示例(小程序端专属)
1 | |
三、小程序端条件编译 全场景实战详解
条件编译是UniApp解决多小程序平台差异的核心方案,通过特殊注释语法,让代码在不同平台编译时仅包含对应端的代码,避免冗余代码、兼容报错,小程序端全场景用法全量详解如下。
3.1 基础语法与平台标识
核心语法
#ifdef 平台标识:如果当前编译平台匹配该标识,编译这段代码#ifndef 平台标识:如果当前编译平台不匹配该标识,编译这段代码#endif:条件编译结束标记
小程序端专属平台标识
| 平台标识 | 对应平台 |
|---|---|
| MP-WEIXIN | 微信小程序 |
| MP-ALIPAY | 支付宝小程序 |
| MP-TOUTIAO | 抖音/头条小程序 |
| MP-BAIDU | 百度小程序 |
| MP-QQ | QQ小程序 |
| MP-KUAISHOU | 快手小程序 |
| MP | 所有小程序平台(不含H5、App端) |
3.2 模板(template)中的条件编译
用于控制不同小程序平台显示不同的组件、内容、功能入口,是最常用的场景,完整示例:
1 | |
3.3 脚本(script)中的条件编译
用于处理不同小程序平台的API差异、授权逻辑、业务处理,避免不兼容API导致的报错,全场景示例:
1 | |
3.4 样式(style)中的条件编译
用于处理不同小程序平台的样式适配、导航栏适配、UI差异,示例:
1 | |
3.5 配置文件(pages.json)中的条件编译
用于处理不同小程序平台的路由、tabBar、导航栏、权限配置差异,示例:
1 | |
3.6 manifest.json 中的条件编译
用于处理不同小程序平台的AppID、编译配置、权限配置,示例:
1 | |
四、小程序端组件与API 全量规范与兼容处理
4.1 组件使用规范(小程序端专属)
- 优先使用UniApp内置组件:必须使用
<view>、<text>、<image>、<button>等跨端内置组件,底层自动编译为小程序原生组件,禁止直接使用div、span等HTML标签,小程序端无法识别。 <image>组件核心规则(高频踩坑)- 必须设置
mode属性(常用widthFix、aspectFit、aspectFill),否则图片会按默认320px*240px尺寸变形 - 支持
lazy-load懒加载属性,长列表图片必须开启,提升滚动性能 - 本地图片必须放在
static目录下,否则打包后无法识别 - 网络图片必须在微信公众平台配置
request合法域名,否则无法加载 - 图片大小限制:本地图片≤2MB,网络图片无大小限制,但建议≤500KB,避免占用内存
- 必须设置
- 小程序原生组件层级规则(核心踩坑点)
小程序端<video>、<map>、<canvas>、<camera>、<input>等原生组件为客户端原生渲染,层级最高,无法通过CSS的z-index覆盖,必须使用<cover-view>、<cover-image>组件才能覆盖在原生组件之上。注意:
<cover-view>仅支持嵌套<cover-view>、<cover-image>、<button>组件,不支持嵌套其他组件,样式支持有限,避免复杂布局。 - 自定义组件规范
- 遵循UniApp的
easycom规范:组件路径符合components/组件名/组件名.vue结构,无需import和注册,直接在页面中使用,小程序端默认开启。 - 小程序端自定义组件命名禁止使用微信原生组件名(如
view、button、ad),避免冲突。 - 自定义组件中获取节点信息,必须使用
uni.createSelectorQuery().in(this),否则无法获取到组件内的节点。
- 遵循UniApp的
- 小程序原生组件使用规则
如需使用微信专属原生组件(如<ad>广告、<official-account>公众号关注组件、<live-player>直播组件),必须配合#ifdef MP-WEIXIN条件编译使用,避免其他平台编译报错。
4.2 API使用规范与封装(小程序端专属)
- 优先使用uni.前缀API:必须使用
uni.request、uni.showToast、uni.setStorageSync等跨端API,底层自动编译为小程序wx.前缀API,禁止直接使用wx.前缀API,否则无法跨端兼容,仅在微信专属API场景下配合条件编译使用。 - 网络请求统一封装(核心必备)
小程序端强制要求:所有网络请求必须使用HTTPS协议,不支持HTTP、IP地址、localhost请求;必须在微信公众平台「开发管理-开发设置-服务器域名」中配置request合法域名,域名必须完成ICP备案,支持TLS 1.2+协议。
必须统一封装请求,处理token、错误码、loading、权限过期等逻辑,完整封装示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103// utils/request.js
// 接口基础域名
const BASE_URL = 'https://api.example.com'
// 无需token的白名单接口
const WHITE_LIST = ['/auth/login', '/auth/register', '/home/banner']
const request = (options) => {
return new Promise((resolve, reject) => {
// 显示loading,可通过options.loading=false关闭
if (options.loading !== false) {
uni.showLoading({
title: options.loadingText || '加载中...',
mask: true // 防止穿透点击
})
}
// 拼接完整url
const url = BASE_URL + options.url
// 获取token
const token = uni.getStorageSync('token')
// 构造请求头
const header = {
'Content-Type': options.contentType || 'application/json',
'Authorization': token ? `Bearer ${token}` : ''
}
uni.request({
url,
method: options.method || 'GET',
data: options.data || {},
header,
timeout: options.timeout || 10000,
success: (res) => {
uni.hideLoading()
const { statusCode, data } = res
// HTTP状态码200处理
if (statusCode === 200) {
const { code, msg, data: result } = data
// 业务成功
if (code === 200) {
resolve(data)
}
// token过期,权限不足
else if (code === 401) {
uni.clearStorageSync()
uni.showModal({
title: '登录过期',
content: '您的登录已过期,请重新登录',
showCancel: false,
success: () => {
uni.reLaunch({ url: '/pages/login/login' })
}
})
reject(data)
}
// 其他业务错误
else {
uni.showToast({
title: msg || '请求失败',
icon: 'none',
duration: 2000
})
reject(data)
}
}
// HTTP状态码非200处理
else {
uni.showToast({
title: `网络错误:${statusCode}`,
icon: 'none'
})
reject(res)
}
},
fail: (err) => {
uni.hideLoading()
// 网络错误处理
uni.showToast({
title: '网络异常,请检查网络设置',
icon: 'none'
})
reject(err)
}
})
})
}
// 封装常用请求方法
export const get = (url, data = {}, options = {}) => {
return request({ url, method: 'GET', data, ...options })
}
export const post = (url, data = {}, options = {}) => {
return request({ url, method: 'POST', data, ...options })
}
export const put = (url, data = {}, options = {}) => {
return request({ url, method: 'PUT', data, ...options })
}
export const del = (url, data = {}, options = {}) => {
return request({ url, method: 'DELETE', data, ...options })
}
export default request - 小程序端专属核心API场景与规范
API场景 核心用法与小程序端硬性规则 登录授权 1. 调用 uni.login()获取code,传给后端换取openid、unionid、session_key,code有效期5分钟,只能使用一次
2. 微信已回收静默获取用户信息能力,获取用户昵称、头像必须通过<button open-type="chooseAvatar">(新版)或wx.getUserProfile触发,必须用户主动点击微信支付 调用 uni.requestPayment(),支付参数(timeStamp、nonceStr、package、signType、paySign)必须由后端生成,前端禁止参与签名计算,避免密钥泄露获取手机号 必须通过 <button open-type="getPhoneNumber">,用户主动点击触发,获取encryptedData和iv,传给后端解密,前端无法直接解密获取手机号;个人主体小程序无此权限订阅消息 调用 uni.requestSubscribeMessage(),获取用户订阅授权,仅能下发已在微信公众平台配置的模板消息,用户拒绝后无法再次弹窗申请定位 调用 uni.getLocation()获取用户位置,必须在pages.json中配置permission权限声明,必须在微信公众平台开通「地理位置接口权限」,否则无法使用扫码 调用 uni.scanCode(),调用微信扫码能力,识别二维码/条形码,无需额外申请权限小程序跳转 调用 uni.navigateToMiniProgram()跳转到其他小程序,必须在pages.json中配置navigateToMiniProgramAppIdList白名单,否则无法跳转本地存储 调用 uni.setStorageSync()/uni.getStorageSync(),单个key存储数据上限1MB,所有数据存储上限10MB,禁止存储大量数据
五、小程序端数据通信与状态管理
5.1 全局状态管理
| 方案 | 适用场景 | 用法示例 | 小程序端注意事项 |
|---|---|---|---|
getApp().globalData |
小型项目、少量全局数据 | - | 1. 仅能在App.vue中定义,全局唯一 2. 数据修改后无法自动响应到页面,需配合watch或事件总线实现响应式 |
| Vuex | Vue2项目、中大型项目、复杂全局状态 | 标准Vuex用法,分模块管理用户、购物车、全局配置等状态 | 小程序端完全兼容,需注意分包中无法直接访问主包的Vuex模块,需统一挂载 |
| Pinia | Vue3项目、全量项目,推荐使用 | 标准Pinia用法,比Vuex更简洁,支持TypeScript、模块化 | 小程序端完全兼容,无分包访问限制,Vue3项目优先选择 |
1 | |
5.2 页面间通信全方案
URL参数传递(最常用)
最基础、最稳定的页面通信方式,通过uni.navigateTo的url拼接参数,目标页面onLoad中接收,适合少量简单参数。1
2
3
4
5
6
7
8
9// 页面A:跳转传参
uni.navigateTo({
url: `/pages/detail?id=123&name=测试商品`
})
// 页面B:接收参数
onLoad(options) {
console.log('页面入参:', options.id, options.name)
}注意:参数长度限制1024字节,超长参数、特殊字符、复杂对象禁止通过URL传递,改用全局存储/事件总线。
事件总线(EventBus)
通过uni.$emit触发事件,uni.$on监听事件,实现跨页面、跨组件通信,适合非父子页面的实时通信。1
2
3
4
5
6
7
8
9
10
11
12
13
14// 页面A:触发事件,传递数据
uni.$emit('refreshOrderList', { status: 1, page: 1 })
// 页面B:监听事件,接收数据
onLoad() {
uni.$on('refreshOrderList', (data) => {
console.log('收到事件:', data)
this.getOrderList(data.status, data.page)
})
},
// 必须在页面卸载时解绑,避免内存泄漏、多次触发
onUnload() {
uni.$off('refreshOrderList')
}全局本地存储
通过uni.setStorageSync()/uni.getStorageSync()存储和读取数据,适合大量数据、复杂对象、持久化数据传递。1
2
3
4
5
6
7
8
9
10
11
12
13// 页面A:存储数据
uni.setStorageSync('goods_detail', {
id: 123,
name: '测试商品',
price: 99.9,
spec: ['红色', 'XL']
})
// 页面B:读取数据
onLoad() {
const goodsDetail = uni.getStorageSync('goods_detail')
console.log('商品详情:', goodsDetail)
}页面栈获取与操作
通过getCurrentPages()获取当前页面栈实例,直接操作上一个页面的数据和方法,适合父子页面通信。1
2
3
4
5
6
7
8
9
10
11
12// 页面B:返回前操作上一个页面A的数据和方法
goBack() {
const pages = getCurrentPages()
// 获取上一个页面实例
const prevPage = pages[pages.length - 2]
// 调用上一个页面的方法
prevPage.getList()
// 修改上一个页面的数据
prevPage.$vm.status = 2
// 返回上一页
uni.navigateBack()
}注意:小程序页面栈最多10层,超出后
navigateTo无法打开新页面,需使用redirectTo替换。
5.3 组件间通信
- 父子组件通信:父组件通过
props向子组件传值,子组件通过$emit触发事件向父组件传值,最基础的组件通信方式。 - 兄弟组件通信:通过共同的父组件中转,或使用事件总线、全局状态管理。
- 跨层级组件通信:Vue2/Vue3均使用
provide/inject依赖注入,或全局状态管理。
六、小程序端专属性能优化全方案
小程序的性能限制比App、H5端更严格,性能优化直接影响小程序的启动速度、流畅度、用户留存,甚至影响微信搜索排名,核心优化方案全量详解如下。
6.1 包体积优化(最核心,影响启动速度与上架)
微信小程序硬性限制主包≤2MB,总大小≤20MB,包体积越小,启动速度越快,是优化的第一优先级。
- 严格执行分包加载(核心中的核心)
- 主包仅保留tabBar页面、公共组件、公共资源,所有非核心页面全部分包,严格控制主包体积≤1.5MB,预留冗余空间。
- 独立分包用于活动页、推广页、H5跳转落地页,不依赖主包,可独立启动,不占用主包体积。
- 合理配置分包预加载,在用户进入首页时,预加载高频访问的分包,平衡启动速度和页面切换体验。
- 分包之间的公共资源,提取到主包内,避免重复打包,占用体积。
- 资源极致优化
- 所有图片、音频、视频等静态资源,尽量上传CDN,仅保留极小的tab图标放在static目录,这是包体积瘦身最有效的手段。
- 图片必须压缩,推荐使用webp格式,比png/jpg体积小50%以上,小程序端全支持。
- 字体文件使用线上地址,仅保留需要的字体子集,禁止全量字体包打包到项目中。
- 剔除未使用的静态资源,开启manifest.json中的「忽略未使用的资源」配置。
- 代码瘦身
- 开启manifest.json中的代码压缩、摇树优化,剔除未使用的代码、组件、依赖。
摇树优化(Tree Shaking)是一种死代码消除(Dead Code Elimination, DCE)技术,核心作用是在打包构建时,精准剔除项目中从未被引用、从未执行的 “无用代码”,从而大幅减少最终生成的代码包体积。 - 避免引入过大的第三方库,如完整的lodash,按需引入工具函数,或自行封装轻量工具方法。
- 开启上传时自动清除console.log,剔除调试代码、注释。
- 合理使用条件编译,剔除其他平台的冗余代码,只保留当前小程序平台的代码。
- 避免在代码中内嵌大段base64图片,改用CDN地址。
- 开启manifest.json中的代码压缩、摇树优化,剔除未使用的代码、组件、依赖。
6.2 渲染性能优化(解决卡顿、掉帧、白屏)
小程序的渲染层和逻辑层分离,所有数据更新都需要通过setData从逻辑层传递到渲染层,频繁、大量的setData是卡顿的核心原因。
- setData极致优化(小程序渲染核心)
- 避免频繁setData,合并多次数据更新,一次性提交,禁止在循环中执行setData。
- 减少setData的数据量,仅更新需要变化的字段,禁止全量更新大对象、长列表,支持路径式更新:
this.setData({ 'list[0].title': '新标题' })。 - 单条setData数据量不超过100KB,过大会占用主线程传输时间,导致渲染延迟。
- 页面隐藏、小程序进入后台后,停止所有setData操作,避免占用后台资源。
- 与渲染无关的数据,不要放在data中,避免触发不必要的setData和重渲染。
- 长列表优化
- 短列表(<100条):配合
onReachBottom分页加载,每次加载10-20条数据。 - 长列表(>100条):必须使用虚拟滚动,仅渲染可视区域的节点,销毁离开可视区域的节点,推荐使用
uni-list、mescroll-uni、uview的长列表组件。 - 列表item结构精简,减少DOM嵌套层级,图片开启懒加载,设置固定宽高,避免渲染时重排。
- 列表item设置唯一key值,禁止使用index作为key,提升重渲染性能。
- 短列表(<100条):配合
- 通用渲染优化
- 频繁切换显示/隐藏的组件,使用
v-show;仅渲染一次的组件,使用v-if,避免频繁销毁重建。 - 页面DOM节点数控制在1000个以内,嵌套层级不超过10层,减少渲染压力。
- 禁止在
watcher、computed、onPageScroll中做复杂计算和频繁的数据更新。 - 自定义组件按需渲染,避免全局注册大量未使用的组件。
- 减少CSS动画的使用,优先使用CSS3硬件加速属性(transform、opacity),避免修改width、height、top等属性导致重排。
- 频繁切换显示/隐藏的组件,使用
6.3 启动速度优化(解决打开慢、白屏问题)
小程序启动速度是微信官方考核的核心指标,直接影响用户体验和搜索排名。
- 主包极致瘦身,主包体积越小,代码下载、注入速度越快,启动速度越快。
- 开启
lazyCodeLoading: "requiredComponents",实现代码按需注入,仅注入当前页面需要的代码和组件,提升启动速度。 - 首页精简,
onLoad/onShow中不做高耗时同步逻辑,先渲染骨架屏,再异步加载数据,减少白屏时间。 App.vue的onLaunch中,非必须的初始化逻辑延迟到首页渲染完成后执行,避免阻塞启动。- 提前预请求,在
onLaunch中预请求首页核心数据,减少等待时间,先拿到数据,页面渲染完成后直接渲染。 - 避免在首页使用过多的自定义组件,减少组件初始化时间。
6.4 内存优化(解决闪退、卡顿、被系统回收)
- 页面
onUnload、组件beforeDestroy时,必须清理所有定时器、延时器、事件监听、websocket、canvas实例,避免内存泄漏。 uni.$on监听的事件,必须在销毁时用uni.$off解绑,避免事件多次触发和内存泄漏。- 避免在data中存放大量不渲染的数据,仅把需要渲染的数据放在data中,减少内存占用。
- 小程序页面栈最多10层,避免层级过深,使用
uni.redirectTo代替uni.navigateTo关闭不需要的页面,释放内存。 - 避免页面内同时渲染大量大图,大图使用缩略图,点击查看原图,图片尺寸不要超过显示尺寸的2倍,减少内存占用。
- 音频、视频、地图组件,在页面卸载时必须销毁,停止播放,释放占用的内存。
七、小程序端调试、兼容与发布上线
7.1 全流程调试方法
- 开发环境调试
HBuilderX中点击「运行」→ 「运行到小程序模拟器」→ 「微信开发者工具」,项目会自动编译并打开微信开发者工具,在开发者工具中进行调试。 - 微信开发者工具调试面板
- Console面板:查看控制台日志、报错信息,执行JS代码,调试逻辑问题。
- Network面板:查看接口请求、响应、请求头、状态码,抓包分析接口问题,支持过滤、断点调试。
- AppData面板:查看页面data数据、全局数据,支持实时修改,调试数据渲染问题。
- Wxml面板:查看DOM结构、样式,调试布局、样式问题,支持实时修改样式。
- Storage面板:查看本地存储数据,支持新增、修改、删除,调试存储相关问题。
- 真机调试面板:扫码连接真机,远程调试真机上的小程序,支持查看日志、网络、存储。
- 真机调试
微信开发者工具点击「真机调试」,扫码在手机上打开小程序,可调试真机上的授权、支付、定位、蓝牙等必须真机才能使用的功能,是发布前必须的测试环节。 - 体验版测试
代码上传到微信公众平台后,可设置为体验版,生成体验码,给测试人员、产品人员测试,模拟正式环境的全功能、全流程测试,是发布前的最后测试环节。
7.2 兼容性处理
- 基础库版本兼容
- manifest.json中设置最低基础库版本为2.10.0以上,可覆盖99%以上的微信用户。
- 高版本基础库新增的API,必须做兼容判断,低版本做降级处理,示例:
1
2
3
4
5
6
7// 判断API是否可用
if (wx.getUserProfile) {
// 支持,使用新API
} else {
// 不支持,降级处理
uni.showToast({ title: '微信版本过低,请升级后重试', icon: 'none' })
}
- 机型与屏幕适配
- 使用
rpx单位(基于750px设计稿)+ flex弹性布局,适配不同屏幕尺寸、分辨率。 - 适配iOS刘海屏、底部小黑条,使用
padding-bottom: env(safe-area-inset-bottom)设置安全区域。 - 自定义导航栏必须适配不同机型的状态栏高度、微信胶囊按钮位置,避免布局错乱。
- 使用
- 多小程序平台兼容
- 通过条件编译处理不同平台的API、组件、样式差异,避免兼容报错。
- 优先使用UniApp跨端API,减少平台专属代码,提升兼容性。
7.3 发布上线全流程
- 代码上传
测试完成后,在微信开发者工具中点击右上角「上传」,填写版本号、项目备注,上传代码到微信公众平台,上传前必须开启代码压缩、清除console.log。 - 提交审核
登录微信公众平台,进入「管理」→「版本管理」,找到刚上传的版本,点击「提交审核」,填写审核信息:- 小程序类目:必须与实际功能一致,特殊类目需要提供对应资质。
- 功能页面:填写小程序的核心页面、功能说明。
- 测试账号:提供完整的测试账号、密码,供审核人员测试所有功能,无登录功能可不填。
- 审核备注:说明小程序的核心功能、特殊逻辑,帮助审核人员快速了解。
- 审核与发布
提交审核后,等待微信官方审核,审核时长通常1-3个工作日,加急审核可缩短到几小时。
审核通过后,进入版本管理,点击「发布」,可选择全量发布、灰度发布(按比例发布),发布后用户即可更新到最新版本。
7.4 审核避坑核心要点
- 必须符合《微信小程序平台运营规范》,无违规内容、违法信息。
- 必须提供完整的《用户隐私保护指引》,小程序首次启动时弹窗提示,获取用户同意后,才能收集用户信息、申请权限,否则审核直接被拒。
- 特殊类目(金融、医疗、教育、新闻、电商等)必须提供对应的资质文件,否则无法通过审核。
- 禁止诱导用户分享、点赞、关注、下载,禁止分享裂变、红包诱导等违规行为。
- iOS端禁止虚拟支付相关内容,包括会员、充值、虚拟商品购买等,必须使用苹果内购,否则审核直接被拒。
- 小程序必须提供完整的功能,不能是简单的H5套壳、官网展示,否则审核被拒。
- 所有申请的权限,必须有对应的功能场景,不能申请无关权限,否则审核被拒。
八、小程序端安全合规要点
- 网络安全
- 所有接口必须使用HTTPS协议,禁止使用HTTP协议,必须在微信公众平台配置合法域名。
- 接口请求做签名校验,防止抓包篡改请求参数。
- 敏感参数、用户信息加密传输,禁止明文传输。
- 配置接口请求频率限制,防止恶意刷接口、CC攻击。
Challenge Collapsar(挑战黑洞),是针对 Web 应用 / 接口的应用层(OSI 七层模型第 7 层,HTTP/HTTPS 层)分布式拒绝服务攻击(DDoS),也是目前最主流、最难防护的业务层攻击方式之一
- 数据安全
- 用户敏感信息(手机号、身份证、银行卡)加密存储,禁止明文存储在本地。
- token设置有效期,定期续期,退出登录时清除所有用户信息。
- 遵循最小必要原则,仅收集功能必须的用户信息,不收集无关的个人信息。
- 禁止泄露、出售、共享用户个人信息,符合《个人信息保护法》要求。
- 合规要求
- 严格遵守《微信小程序平台运营规范》《网络安全法》《个人信息保护法》《数据安全法》等法律法规。
- 制定完整的《用户隐私保护指引》《用户服务协议》,明确告知用户数据收集的用途、范围、存储期限,获取用户同意后才能收集。
- 权限申请必须明确告知用途,在用户使用对应功能时才申请,禁止启动时一次性申请所有权限。
- 小程序内容、功能必须与注册类目一致,禁止超范围经营。
- 禁止提供违法、违规、低俗、侵权的内容和服务。