

“Write Once, Run Everywhere” 是所有前端开发的终极梦想。Uni-app 作为基于 Vue.js 的跨端框架,确实降低了多端开发的门槛。但在实际项目中,真正的“一套代码”往往伴随着大量的条件编译和平台特异性处理。
本文基于真实项目经验,总结了从 H5、微信小程序到 App(iOS/Android)跨端开发中的核心坑点与适配策略。
#ifdef / #ifndef 是跨端的基础。不要试图用一套逻辑强行覆盖所有端,uni-app 提供的条件编译是解决差异化的最有效手段。
#ifdef %PLATFORM%:仅在某平台存在。#ifndef %PLATFORM%:除了某平台均存在。%PLATFORM% 取值:H5、MP-WEIXIN、APP-PLUS 等。// 获取用户信息
getUserInfo() {
// #ifdef MP-WEIXIN
// 微信小程序逻辑:wx.getUserProfile
uni.getUserProfile({
desc: '用于完善会员资料',
success: (res) => this.saveUser(res.userInfo)
});
// #endif
// #ifdef APP-PLUS
// App 逻辑:通过 SDK 登录或原生插件
uni.login({
provider: 'weixin',
success: (res) => this.getAppUserInfo(res)
});
// #endif
// #ifdef H5
// H5 逻辑:公众号网页授权
window.location.href = 'https://open.weixin.qq.com/...';
// #endif
}最佳实践:
取消原生导航栏(navigationStyle: "custom"),封装一个全局的 <CustomNavbar> 组件,内部根据 uni.getSystemInfoSync() 获取 statusBarHeight 和 titleBarHeight 进行动态占位。
在 iOS 底部带有“黑条”的设备上,绝对定位的按钮容易被遮挡。
.footer-btn {
position: fixed;
bottom: 0;
/* 适配底部安全区 */
padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
}rpx 在小程序和 App 端表现良好,但在 H5 端(尤其是 PC 浏览器访问 H5 时)可能会变得巨大。
解决方案:
限制最大宽度:在 pages.json 中配置 globalStyle:
"rpxCalcMaxDeviceWidth": 960, // rpx 计算所支持的最大设备宽度
"rpxCalcBaseDeviceWidth": 375, // rpx 计算使用的基准设备宽度
"rpxCalcIncludeWidth": 750 // rpx 计算特殊处理的设备宽度PC 专用布局:利用 match-media 组件或 CSS 媒体查询,为 PC 端提供两栏或三栏布局,而不是简单粗暴的拉伸。
uni.login 获取 code)+ 用户授权(getUserProfile)。uni.requestPayment,参数由后端签名返回。小程序和 App 支持 uni.uploadFile,路径通常是 _doc/ 或 wxfile:// 开头的临时路径。但 H5 端受限于浏览器安全策略,uni.chooseImage 返回的是 blob: 链接。
H5 特殊处理:
如果需要将图片转为 Base64 或进行压缩,H5 端需要使用 Canvas 或 FileReader,而 App/小程序端通常推荐使用 uni.compressImage 或 image-compressor 等原生方式,避免 JS 线程阻塞。
// H5 端图片压缩示例
// #ifdef H5
async function compressImageH5(file) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (e) => {
const img = new Image();
img.src = e.target.result;
img.onload = () => {
const canvas = document.createElement('canvas');
// ... 绘制并导出为 blob
canvas.toBlob(resolve, 'image/jpeg', 0.8);
};
};
});
}
// #endif虽然 uni.connectSocket 是标准 API,但心跳机制和断线重连在 App 锁屏后(Android 后台保活问题)表现差异极大。
GoEasy 或 UniPush)来维持长连接,或者在 JS 层实现健壮的心跳检测与重连机制。uni-app 在 App 端默认使用 WebView 渲染(类似小程序架构),在处理长列表或复杂动画时性能不如原生。
NVUE 基于 Weex 引擎,底层渲染为原生组件(Native View)。
混合开发策略:
90% 的普通业务页面使用 .vue,10% 的核心性能页面使用 .nvue。
uni-admin 或自建版本管理接口,利用 plus.runtime.install 实现静默热更新(wgt 包)。manifest.json 中的 proxy。#ifdef MP-WEIXIN 代码块,灰置其他平台的代码,利用这一点快速检查逻辑分支。Uni-app 并不是“银弹”,它更多是用 20% 的特定适配代码换取了 80% 的逻辑复用。