必须用条件编译(如 #ifdef mp-weixin 或 #ifdef app-plus)才能准确区分微信小程序和原生 app,因为 uni.getsysteminfosync().platform 返回设备系统而非目标平台,uni.getenv() 仅适合非关键路径的运行时轻量判断。

不能靠 uni.getSystemInfoSync().platform 判断“是小程序还是 App”,它返回的是底层设备类型(比如 android 或 ios),不是你编译的目标平台。真正要区分「代码跑在微信小程序里」还是「跑在原生 App 里」,必须用条件编译。
为什么 uni.getSystemInfoSync().platform 不可靠
这个 API 返回的是运行时宿主环境,不是目标平台:
- 微信小程序真机上可能返回
android(因为 WebView 跑在安卓系统里) - H5 页面里返回
web,但uniPlatform才是h5 - App 平台下返回
ios或android,和APP-PLUS完全不对应 - 鸿蒙设备可能返回空字符串或
harmony,而uniPlatform是app
所以拿它做平台路由分发,大概率在开发者工具、模拟器、不同厂商设备上出错。
uni.getEnv() 的 PLATFORM 字段能用吗
可以,但仅限于运行时轻量判断,且有版本和兼容性限制:
- 要求 uni-app 版本 ≥ 1.9.0,HBuilderX ≥ 3.4.10
- 返回值如
mp-weixin、app-plus、h5,比platform更贴近目标平台 - 但它仍是运行时读取,无法规避跨平台 API 调用报错(比如在 H5 里误执行
plus.runtime.getProperty()) - 某些低端安卓 WebView 或旧版微信基础库里,
uni.getEnv()可能未定义或返回空对象
建议只用于日志上报、灰度开关等非关键路径,别用来决定是否 import 某个平台专属模块。
必须用条件编译:#ifdef MP-WEIXIN vs #ifdef APP-PLUS
这是唯一能 100% 确保逻辑只出现在目标平台的方式,编译阶段就剔除无关代码:
- 判断是否为微信小程序:用
#ifdef MP-WEIXIN,不是mp-weixin(大小写敏感,且不能带引号) - 判断是否为 App(iOS/Android 原生包):用
#ifdef APP-PLUS,不是app或app-plus - 宏名必须严格匹配文档,比如
MP-ALIPAY、H5、MP(泛指所有小程序) - 条件编译注释必须紧贴代码,中间不能有空行或其它注释,否则整块被跳过
示例:
#ifdef MP-WEIXIN
wx.login({ success: res => console.log('小程序登录') })
#endif
#ifdef APP-PLUS
const ver = plus.runtime.version
console.log('App 版本:', ver)
#endif
微信内 H5 和微信小程序的边界容易混淆
同一个 URL 在微信里打开,可能是 H5,也可能是小程序 web-view 嵌入页——这时 uniPlatform 都是 h5,但运行上下文完全不同:
- 微信内 H5 的
navigator.userAgent含Micromessenger,但uni.getEnv().PLATFORM仍是h5 - 小程序 web-view 里的 H5 页面,
uni.getEnv()无法识别其父容器是小程序,只能靠window.__wxjs_environment === 'miniprogram'或微信 JS-SDK 的wx.miniProgram.getEnv回调确认 - 如果要做「微信内 H5 不展示某按钮,小程序 web-view 里要展示」,就得组合判断:
uni.getEnv().PLATFORM === 'h5' && /micromessenger/i.test(navigator.userAgent)+ 微信 SDK 探测
这种混合场景下,光靠 uni-app 自身 API 不够,得引入微信官方机制,而且必须加 try/catch 防止 SDK 未加载时报错。











