资讯动态

uniapp页面开发实战:路由、生命周期与跨端适配全解析

发布时间:2026/10/14 14:40:15 来源:尧图企业网站定制
做 uniapp 开发这几年我最大的感受是很多人把精力全花在学框架语法、啃 API 文档上可真到了做一个完整项目的时候最头疼的反而是页面这一层。页面的路由怎么组织、生命周期到底什么时候触发、跨端之后样式为什么变了、tabBar 为什么切换时闪一下、地图和支付在 App 和小程序里为什么表现不一样——这些才是真正拉开差距的地方。这篇文章不聊虚的我把 uniapp 页面从创建、配置、通信、组件化到功能集成、打包上架、问题排查的完整链路拆开讲一遍全是项目里反复验证过的东西适合正在用 uniapp 做多端项目的开发者也适合准备面试前系统梳理一遍的同学。1. 页面运行机制拆解路由、生命周期与页面间通信1.1 页面栈与路由跳转的底层逻辑uniapp 的页面管理无论你最终编译到微信小程序、App 还是 H5底层都逃不开一个页面栈的概念。说白了页面栈就是一个后进先出的数组你每打开一个新页面它就被压入栈顶每关闭一个页面它就被弹出。这套逻辑和浏览器历史记录、微信小程序的页面栈本质上是一回事只是 uniapp 帮你做了一层统一封装。实际开发中要特别注意uni.navigateTo和uni.redirectTo的区别。navigateTo是压栈页面会保留在栈中可以返回redirectTo是替换当前页面当前页面被销毁新页面占据它的位置。很多人刚开始用的时候不区分这两个结果就是页面栈越堆越深微信小程序端超过 10 层之后navigateTo会直接失败。而且一旦超过 10 层用户点返回会感觉卡住了因为页面栈已经乱套。我的经验是详情页跳详情页这种场景如果不需要保留中间页优先用redirectTo而像首页跳列表、列表跳详情这种典型的返回路径清晰的场景才用navigateTo。还有一个容易被忽略的是uni.switchTab和uni.navigateBack的配合。switchTab会关闭所有非 tabBar 页面并把 tabBar 页面切到指定那一页但它的跳转目标是 tabBar 页面时才能用。如果你试图用navigateTo跳 tabBar 页面会报错找不到页面。反向排查的时候很多人问为什么我跳转过去页面空白十有八九是路由 API 用错了。页面栈的排查工具也别错过。在 H5 端可以直接看浏览器历史但小程序端和 App 端你就得靠getCurrentPages()这个方法。它返回当前页面栈的实例数组最后一个元素就是当前页面。我在调试多层跳转的时候经常用它打印页面栈深度一眼就能看出来是不是有页面没被正确关闭。另外getCurrentPages()返回的页面实例上可以拿到$page、options等属性也能直接调用页面实例上的方法这在跨页面操作时是个非常好用的后门。1.2 生命周期钩子的执行时机与跨端差异uniapp 的页面生命周期是面试和实战里的高频考点。最核心的四个是onLoad、onShow、onReady、onHide外加一个onUnload。它们的触发顺序是onLoad最先执行只执行一次此时页面还没渲染完成拿不到完整的 DOM 尺寸接着onShow执行表示页面可见每次从后台回到页面都会触发然后onReady执行此时页面渲染完成可以安全操作 DOM 或 canvas最后页面被关闭时执行onUnload。跨端差异是这里的重头戏。比如onLoad的参数微信小程序端会拿到上一个页面通过 URL 拼接传递的参数App 端也兼容这种形式但 H5 端在第一次加载时onLoad的 options 可能拿不到需要从window.location或uni.getLaunchOptionsSync里取。更典型的差异是onShow的执行频率。App 端切换到后台再回前台onShow一定会触发小程序端同样但 H5 端如果用户切走浏览器标签页再切回来不一定走onShow因为 H5 的可见性用的是浏览器 Page Visibility APIuniapp 虽然做了监听但某些浏览器行为不完全一致。处理这种差异我的习惯是不要在页面的生命周期里写依赖端差异的强逻辑。如果某个操作必须每次页面可见时刷新就显式放在onShow里但同时在onLoad里做一次初始化标记避免onShow和onLoad重复请求。比如商品详情页首次进入和从支付回调返回都需要刷新订单状态但首屏数据只需要请求一次。我的做法是用一个this.inited标志位onLoad里设为 true 并请求首屏onShow里判断如果this.inited为 true 就只做增量刷新。还有onReachBottom、onPullDownRefresh这两个滚动相关的生命周期。注意它们只在页面滚动场景下生效如果你页面内容是scroll-view组件包裹的而不是页面原生滚动那onReachBottom就永远不会触发。这个问题我见过好几个人踩坑。scroll-view有自己的scrolltolower事件和页面级onReachBottom是两套机制别混用。1.3 页面间通信的几种姿势与选型页面间通信是页面开发绕不开的话题。最原始的方式是 URL 参数传递适合简单数据但遇到对象、数组就得encodeURIComponent(JSON.stringify(obj))而且 URL 长度有限制复杂数据传起来很别扭。第二种方式是用全局变量或uni.setStorageSync适合跨页面共享状态但要自己管理清理时机不然容易造成数据残留。第三种是uni.$emit和uni.$on事件总线适合某个页面做了操作其他页面需要感知的场景比如购物车角标数量变化、登录状态变化。事件总线虽然好用但有个致命问题不自动销毁。页面卸载后如果uni.$on的监听没有在onUnload里uni.$off会一直驻留在内存里。轻则重复触发逻辑重则内存泄漏。我的规范是在onLoad里注册监听在onUnload里统一uni.$off并且回调函数用命名函数别用匿名箭头函数否则off的时候无法精确定位。如果你项目复杂度高页面之间共享的状态很多我建议趁早引入 Pinia 或 Vuex。uniapp 官方也推荐在 vue3 项目里用 Pinia。有了全局 store跨页面的数据同步就变得很自然不再需要事件总线满天飞。但注意 Pinia 在 uniapp 里的一个坑如果 store 里保存了非响应式的外部对象比如某些 canvas 实例、地图实例在小程序端可能会因为序列化问题报错。我一般只在 store 里放纯数据复杂实例一律不放。2. 页面配置与跨端适配从 pages.json 到 manifest 再到条件编译2.1 pages.json 是页面的总调度中心pages.json 相当于整个项目的页面上层建筑规划图。第一项pages数组决定了页面路由表数组第一项就是启动页。这意味着你改启动页不只是删掉旧的加个新的而是把这个页面挪到数组第一位。很多人上线后发现 App 打开不是想要的首页多半是没注意这个第一项即首页的规则。globalStyle里配置全局窗口样式navigationBarBackgroundColor、navigationBarTitleText、backgroundColor这些。每个页面也可以通过style字段覆盖全局配置比如某个页面需要沉浸式导航就单独设置navigationStyle: custom但这会连返回按钮、标题栏一起隐藏你需要在页面里自己补一个自定义导航栏。我的经验是自定义导航栏虽然灵活但适配成本高尤其是状态栏高度在不同端不一样你需要用uni.getSystemInfoSync().statusBarHeight动态撑开否则 iPhone 的刘海和 Android 的状态栏会把你精心设计的标题顶到天上去。tabBar配置是页面的一个重点。text、iconPath、selectedIconPath 三件套图标大小建议 81x81 像素否则在不同设备上会糊。还有一个细节是tabBar的list最少 2 项最多 5 项超过 5 个 tab 你只能放弃原生 tabBar改用自定义 tabBar。自定义 tabBar 的玩法很多可以加中间凸起按钮、动态隐藏 tab 等但要在每个 tab 页面里同步维护选中状态稍微麻烦一点。2.2 manifest.json 与多端能力开关manifest.json 是 uniapp 项目的身份证。appid、应用名称、版本号、小程序 appid 都在这里配置。需要注意微信小程序的 appid 和在微信公众平台注册的 AppID 是一一对应的如果你暂时没注册可以用测试号但测试号里很多能力比如支付、分享不可用。manifest 里最容易被忽略的是模块权限配置这一栏。App 端使用地图、支付、推送、语音输入等功能都需要在 manifest 里勾选对应模块并配置对应的 SDK 参数比如高德地图的 key、微信支付的 appid。不勾选模块你调uni.chooseLocation或plus.maps这类 API 会直接无响应而且不会报清晰的错误。这个坑几乎每个上架 App 的团队都会踩一遍我见过有人排查了大半天最后发现是 manifest 模块没勾。H5 端在 manifest 里还有运行基础路径和路由模式配置。路由模式默认 hash刷新页面不会 404但 URL 带 # 号history 模式 URL 好看但服务端要做重定向。用 history 模式时nginx 里需要配置 try_files 指向 index.html不然用户手动刷新或分享出来的链接会白屏。如果你的 H5 需要同时指向两个域名比如一个是用户端、一个是管理端我的做法是打包时用环境变量区分构建路径或者在 manifest 里配置不同的h5.router.base但更省事的方案是跑两套构建脚本用process.env.NODE_ENV结合cross-env传递域名标识在代码里统一封装请求基地址。2.3 条件编译一套代码多端各异条件编译是 uniapp 跨端的灵魂。写法是在注释里声明平台标识比如// #ifdef APP-PLUS、// #ifndef H5、// #endifVue 模板里用!-- #ifdef MP-WEIXIN --。编译时 uniapp 会直接把不匹配平台的分支代码删除所以条件编译里的代码不会被打包到其他端也不会引起运行时错误。实际项目中条件编译用的最多的地方是支付逻辑小程序走uni.requestPaymentApp 走plus.payment、地图选点各家地图 API 不同、分享小程序用onShareAppMessageApp 用plus.share。但条件编译别滥用我能看到最糟糕的代码是一个页面里十几处#ifdef可读性极差。更好的做法是封装一个统一的 service 层把端差异收敛在几个函数里页面里只调用封装后的方法。开发工具方面也要注意。HBuilderX 是官方 IDE内置了运行到各端的编译器和模拟器一键运行很方便。但很多团队习惯用 vscode 写代码所以 uniapp 官方也支持在 vscode 里通过插件比如 uniapp-cli-vite开发再用命令行或 HBuilderX 做编译。我的体会是vscode 写代码体验比 HBuilderX 舒服但 HBuilderX 的打包、真机运行、manifest 可视化配置更方面所以我的工作流是 vscode 写代码 HBuilderX 打包调试两边搭配着用。3. 页面组件化与样式细节从组件通信到样式穿透3.1 组件设计与父子通信规范页面里的功能块拆成组件才能复用。uniapp 里最推荐的是 easycom 规范组件放在components目录下组件名和文件名保持一致页面里直接使用无需 import 和注册。这个机制能省大量重复代码。比如你封装了一个price-tag组件放到components/price-tag/price-tag.vue所有页面都能直接用price-tag不用在script里引入。父子组件通信props 向下传数据$emit向上抛事件。这里有个规范性问题props 尽量校验 type别一股脑全是Object否则排查 bug 时连数据类型错误都定位不到。$emit的事件名建议用 kebab-caseupdate:visible父组件监听时用update:visible。如果是 vue3 的 script setup 写法defineProps 和 defineEmits 是编译宏不需要导入。自定义事件里最容易出的问题在子组件里直接修改 props 的值。这在 vue2 里会报错在 vue3 里虽然不报错但会破坏单向数据流。正确做法是子组件接收 props 后复制到自己的 data 或 computed 里修改时$emit让父组件改。比如一个弹窗组件的 visible子组件内部关闭时不要直接this.visible false而是this.$emit(update:visible, false)。3.2 组件之间的样式穿透与作用域隔离scoped 样式是 vue 的标配uniapp 也一样。但跨端之后scoped 的行为在小程序和 App 端会有差异。最典型的需求是在父组件里想改子组件内部的样式比如改第三方组件的按钮颜色。vue2 里可以用/deep/vue3 里用:deep()。写法如下/* vue3 */ .parent-class :deep(.child-class) { color: red; }微信小程序里 scoped 的原理是用>swiper classbanner previous-margin40rpx next-margin40rpx current1 circular swiper-item v-foritem in list :keyitem.id image :srcitem.src modeaspectFill / /swiper-item /swiper用previous-margin和next-margin等于给 swiper 容器左右各留出 40rpx 的透视区这样左右两个相邻项就能露出来。要注意的是swiper-item里不要直接放带圆角的卡片时把背景色透出来否则视觉上很突兀。富文本解析是另一个高频需求。接口返回的 HTML 内容小程序端不能用v-html直接渲染这时候就用mp-html组件。它是一个富文本解析组件支持v-html的替代方案能渲染图片、视频、表格。用的时候注意图片的自适应设置:lazy-loadtrue并给img标签设置max-width: 100%否则大图会溢出屏幕。页面里要放图表的话vue3 项目里最常用的是echarts配合renderjs或 canvas。在 H5 端可以直接用 echarts 的 dom 初始化但在小程序端要用ec-canvas组件而且 echarts 的体积比较大建议按需引入比如只引入 LineChart、BarChart。实际开发中我踩过的坑是canvas 的容器初始宽高为 0图表初始化时获取不到尺寸导出图片时白图。解决方法是等onReady之后用uni.createSelectorQuery()获取容器尺寸再初始化图表。4. 页面里的功能集成地图、支付、分享、视频与语音4.1 地图接入的多端适配思路地图在 uniapp 里的接入方式不同端差别很大。H5 端通常用百度地图或高德地图的 JS API直接在 index.html 里引脚本微信小程序端用wx.chooseLocation或 map 组件需要在公众平台配置域名白名单App 端则需要原生的地图 SDK。如果你要接天地图适配逻辑也类似。天地图在 H5 端可以引入天地图的 JavaScript API在小程序端因为天地图官方没有提供小程序 SDK你需要用web-view内嵌 H5 页面或者自己把天地图的瓦片地址转成L.tileLayer类似的切片服务接入 canvas。这个过程中最核心的是 API key 的配置每个端都要单独申请 key而且域名白名单要填对不然请求会被拦截。我的跨端地图选型原则是能用map组件的场景绝不用 web-view。map组件是原生组件性能好、手势流畅但是层级最高容易被其他元素遮挡。如果你在页面上有弹窗、下拉框需要覆盖在地图上就得用cover-view来做覆盖层普通 view 是压不住原生 map 的。另外map在小程序端有数量限制一个页面最多只能用同层渲染的两个 map多了会黑屏。4.2 App 支付与小程序支付的底层差异支付是页面功能里最容易出问题的模块而且很多人混淆App 支付和小程序支付的流程。两者的共同点是都依赖微信支付后台都需要 appid、商户号、预支付订单。但参数集合完全不同。小程序端调uni.requestPayment需要timeStamp、nonceStr、package值是prepay_idxxx、signType、paySign这些参数由后端统一下单接口返回。App 端则要先通过uni.login拿到 code后端用 code 换 openid再统一下单下单成功后客户端用plus.payment调起微信支付 SDK。这里有一个常见的坑很多人在 App 端和小程序端共用了同一套后端下单逻辑结果 App 端拿不到paySign或者调不起支付就是因为 App 端的支付签名参数名和生成规则跟小程序不一样。微信官方文档写得很清楚App 支付用的是partnerId、prepayId、nonceStr、timeStamp、sign这一套以MD5或HMAC-SHA256签名字段名不同不能混用。还有一个细节App 端打包时必须在 manifest 里填写微信支付的 appid 和 urlscheme在微信开放平台创建移动应用并完成应用签名。如果 urlscheme 配错了调起支付后无法回调到 App用户付完钱页面却停留在原地体验非常差。上架应用市场时很多审核不通过就是因为支付回调 scheme 不规范。4.3 自定义分享、视频展示与语音输入分享功能也是页面常见的集成点。小程序端自定义分享好友分为两种一是右上角菜单转发需要在页面里定义onShareAppMessage返回 title、path、imageUrl二是页面内自定义按钮触发按钮要用open-typeshare并且页面里同样要有onShareAppMessage。这个open-typeshare很容易被忽略写成普通click再去调uni.share在小程序端是不生效的。App 端分享则是另外一套逻辑用plus.share调起系统分享或微信 SDK需要引入对应的分享模块并配置 SDK key。多端统一的做法是封装一个share()函数内部用条件编译区分端。要注意分享图片在小程序端要求是 URL 或本地路径不能是 base64App 端反而支持 base64但微信分享的缩略图大小限制在 32KB 左右超过会被裁掉或失败。商品展示视频在页面里用video组件。要注意小程序端 video 同样是原生组件层级高覆盖问题类似 map。另外视频首帧图片poster建议用封面图否则加载时黑屏很影响体验。App 端如果要对视频做自定义控制条可以用cover-view或改用renderjs。语音输入如果不想自己接原生 SDK可以直接使用插件市场里的免费插件比如语音输入类插件底层依赖讯飞或微信同声传译。安装插件后在页面里调用插件暴露的组件和方法返回识别文本。这类插件通常在 H5 端与小程序端的兼容性不完全一致App 端很可能需要原生插件打包选插件的时候一定要看它标注的端兼容情况。4.4 页面内的 web-view 与 H5 交互web-view是嵌入外部 H5 页面的组件非常适合承载复杂的富交互页面比如商品 3D 展示、问卷系统、法律协议文本。它本质上是一个浏览器壳所以网页里写的是一套普通 H5 代码你在 uniapp 里需要和这个 HTML 页面通信时可以用uni.postMessage和监听onMessage。我在实际项目中嵌入 web-view 时最常遇到的问题是去下载图片或调试网页。比如 H5 页面里实现图片下载HTML 端可以用a download或者 canvas 转 blob 触发下载但套进 App 的 web-view 里download属性经常失效。解决方案是通过uni.postMessage把图片 URL 传给 uniapp 外层用uni.downloadFileuni.saveImageToPhotosAlbum完成保存。这要求在 HTML 里引入uniapp的 js-sdk并且调用uni.postMessage的时机要在页面被销毁或分享时才稳定触发这是个官方已知的小坑。5. 打包、上架与安全防护从 APK 到应用市场的最后一步5.1 打包 APK 的流程与证书配置把 uniapp 项目打包成 APK现在最无脑的方式是 HBuilderX 的云打包。在 HBuilderX 里选择发行-原生App-云打包勾选 Android填好包名、证书、图标等待云端构建完成。云打包的好处是不需要本地配置 Android Studio缺点是要排队而且部分原生插件在云打包里要付费或需要自有证书。如果你需要本地打正式包建议用「离线打包」也就是用 Android Studio 下载 uniapp 官方的离线 SDK把前端资源打包进原生工程里。这套流程适合需要接入自研原生模块的团队。对大部分中小项目云打包够了但要提前准备好 Android 证书.keystore 文件。生成证书可以用 keytool 命令行也可以直接用 HBuilderX 的证书生成工具。证书的 alias、密码、有效期要好好保存一旦丢失已经上架的应用市场版本无法升级因为签名不一致。打包时还要留意targetSdkVersion。现在 Android 市场普遍要求 targetSdkVersion 达到 30 以上如果太低上架会提示兼容性风险如果太高应用内一些旧版 sd 卡存储逻辑会出问题。uniapp 云打包默认会配置合理的 targetSdk但你如果是离线打包一定要检查一下自己的工程配置。真机调试和正式包还有一个区别正式包必须勾选使用证书并填密码否则安装时会提示签名不一致。5.2 安卓应用市场上架的注意事项上架安卓应用市场最基础的材料是应用图标、应用截图通常要求 5~8 张、隐私政策、软著或著作权证明。不同市场对隐私政策的要求已经在收紧如果你的应用涉及采集用户信息位置、相机、麦克风必须在隐私政策里明确列出。uniapp 的项目里很多 SDK 会自动采集设备信息所以你上架前最好在 manifest 里关掉不必要的统计 SDK否则审核会被打回。隐私弹窗是另一个重点。App 首次启动时必须先弹窗告知用户隐私政策用户同意后再初始化各 SDK。这个顺序如果反了在某些应用市场是直接拒绝的。uniapp 的plus.runtime里可以设置启动时隐私提示的配置在 manifest 的 App 模块里找到隐私协议弹窗并填写协议链接。我对接过的经验是优先用官方这个配置不要自己用 uni.showModal 在页面里模拟因为时机不对官方配置是在 JS 引擎初始化前弹的更合规。5.3 防止录屏与页面安全很多项目有防录屏的需求。先说结论任何前端方案都无法绝对阻止录屏但可以做到增加了录屏成本。Android 端系统层提供了FLAG_SECURE标志位一旦 window 设置了该标志录屏时该窗口内容会变黑或马赛克。uniapp 的 App 端可以通过plus.android调用原生 API 设置。代码大致如下// 仅 App-Android 端可用 let main plus.android.runtimeMainActivity(); plus.android.importClass(main); let win main.getWindow(); plus.android.invoke(win, addFlags, 8192); // 8192 即 FLAG_SECUREiOS 端没有对等的统一 API只能通过检测录屏通知UIScreen.capturedDidChangeNotification来感知检测到录屏时文字水印或隐藏敏感内容。H5 端则更弱浏览器的 MediaRecorder 可以录走整个页面前端能做的是在全屏视频播放时加提示、给页面加动态水印方便事后追溯。我的建议是不要把宝全押在防录屏上而是给敏感页面加动态水印 禁止截屏反馈的组合。水印最好包含用户手机号或账号信息这样即使被录屏也能定位到人。页面安全不是某个单独功能而是一个体系uniapp 能做的是在合规范围内尽量提高门槛。6. 常见问题与排查技巧实录6.1 H5 页面 network unavailable 之谜很多人运行 H5 端打开控制台看到network: unavailable第一反应以为是网络断了其实不是。这个提示在大部分情况下是因为页面加载了跨域资源而服务端没有返回正确的 CORS 头浏览器把请求拦截了。排查思路是先看是哪个请求报错如果是请求自己接口检查后端是否允许跨域如果请求的是图片或地图瓦片检查是否开启了防盗链。还有一种情况比较隐蔽项目启动时.env环境变量没配好导致请求的 baseURL 是空或 undefined拼出来的 URL 变成了http://undefined/api/xxx控制台显示 network unavailable。我遇到过一次排查了很久最后发现是.env.development文件名拼错了。所以遇到 network unavailable先打印Location里的小程序启动参数和请求 baseURL再做下一步判断。6.2 iOS Safari 下 canvas 导出白图这是个非常经典的问题。iOS Safari 在requestAnimationFrame或连续绘制 canvas 时如果绘制队列没有及时 flush你调用uni.canvasToTempFilePath导出图片时拿到的就是一个空白画布。因为导出时机早于 canvas 实际绘制完成。解决办法有两种。第一用canvas的toDataURL方法前先手动调用一次ctx.draw并且等待回调第二在导出前延迟 200~500ms给绘制队列留出刷新时间。我在实战中更推荐第二种方式简单直接setTimeout(() { uni.canvasToTempFilePath({ canvasId: myCanvas, success(res) { // res.tempFilePath } }); }, 300);如果你的 canvas 绘制是异步的比如加载网络图片后再绘制那就要等图片onload完成后再进入导出逻辑否则导出的图也会是空白或者缺图。6.3 扫码不清晰与自定义扫码页uniapp 里调uni.scanCode可以唤起系统扫码但如果你集成的是第三方扫码插件或自己用 camera 组件做扫码页常见的问题就是扫码不清晰、识别率低。大部分情况下不是摄像头不清晰而是扫码框距离过近或者对焦没触发。用 camera 组件时尽量保证被扫区域有充足光线并让二维码在画面中至少占到 60% 以上的面积。如果只是偶尔识别失败多扫几次能接受那维持现状也可以。但如果是高频扫码场景建议改用插件市场的成熟扫码插件它们内置了识码算法和相机的连续对焦策略比纯粹靠 camera 拼裁切稳定得多。另外自定义扫码页里镜头权限的申请要放在初始化相机之前否则 iOS 首次弹授权时相机画面会黑屏。6.4 切换页面时底部导航闪烁tabBar 闪烁的问题多半发生在切换 tab 瞬间或tab 页面上图片较多时。原因是 tab 切换时页面重新渲染图片资源还没加载完成布局出现抖动或短暂空白。我的排查步骤是这样的第一步看是不是 tabBar 页面用了自定义导航栏或 gif 动图动图会造成每帧重绘闪烁尤其明显第二步看页面里的image是否都有明确的宽高图片没宽高时渲染引擎在图片加载前后会反复计算布局造成闪烁第三步检查 tab 切换时是否触发了大数据量请求如果首屏渲染被同步任务阻塞切换动画就会掉帧。解决方案对应地做图片全部设置宽高或modeaspectFit列表懒加载tab 切换时不要在主线程上做重型计算。如果还闪就把 tab 页的首屏渲染做瘦身能延迟加载的组件放到onReady之后用v-if控制。6.5 开发调试里的小工具与小技巧开发微信小程序时很多人习惯在 HBuilderX 里点了运行到小程序模拟器之后再用微信开发者工具看日志。这个过程如果提示找不到项目可以先手动在微信开发者工具里导入dist/dev/mp-weixin目录。另外微信开发者工具可以打开app.json直接看页面的路由表结构排查页面路径错误非常方便。调试 H5 端时network面板和console是基本操作。调试 App 端则用uni官方提供的真机运行 vConsole在 manifest 里打开调试模式后页面上会出现悬浮的 vConsole 按钮能看到 console 和网络请求。如果你同时在 vscode 里写代码注意 HBuilderX 和 vscode 不要同时监听同一个文件目录否则会出现编译冲突。SQLite 在 uniapp 里的用法如果你做的是离线数据存储需求可以用plus.sqlite它只能在 App 端使用H5 端就用 localStorage 或 IndexedDB小程序端则用 wx.setStorageSync。这个也是跨端开发里很容易忽略的一点很多人写了一套 SQLite 逻辑拿到 H5 上就没数据了因为 H5 没有 plus 环境。7. 聊聊我对 uniapp 页面开发的真实感想做到这里其实已经覆盖了 uniapp 页面开发从骨架到血肉的大部分内容。我个人踩过最大的坑从来不是某个 API 不会用而是没有建立起端差异优先的思维方式。同一个页面在微信小程序里顺滑得很换到 App 上就出现原生组件遮挡、iOS 白屏再换到 H5 上又是跨域和路由问题。如果你一开始就把多端差异纳入设计比如把平台相关的能力全部收口到 service 层、页面里只用封装后的方法后面会省下大量排查成本。还有一个体会是页面性能问题永远比功能问题难修十倍。功能问题有报错、有堆栈慢慢追总能找到性能问题往往是感觉卡了偶尔闪一下在低端机上特别明显这种问题需要你自己主动去压测提前给图片定尺寸、把大列表做分页、把首屏组件拆出来按需加载等到用户反馈再动手就晚了。uniapp 这套框架本身有它的局限比如原生组件层级的限制、条件编译带来的代码可读性问题但它确实让一个人维护多端项目成为可能。页面开发的核心说到底就是把用户的每一次点击、每一次滑动、每一次等待都安排得明明白白。平时多用getCurrentPages、多断点看生命周期、多留意网络面板里的每一个失败请求这些看起来琐碎的习惯才是项目稳定上线最重要的保障。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑