应使用条件编译而非uni.getsysteminfosync().platform判断平台,因其返回底层运行环境而非目标平台;条件编译在编译阶段剔除无关代码,体积小、无兼容风险,且能100%确保逻辑仅出现在目标平台。
不能靠 uni.getsysteminfosync().platform 判断“当前是微信小程序还是 h5”,它返回的是底层运行环境(比如 ios webview),不是你编译的目标平台;真正要区分“代码跑在哪个目标平台”,必须用条件编译,运行时判断只适合查设备能力。
什么时候该用条件编译而不是运行时 API
条件编译在构建阶段就剔除无关代码,体积小、无兼容风险,且能 100% 确保逻辑只出现在目标平台。运行时 API 如 uni.getSystemInfoSync() 返回值受真机系统、WebView 内核、模拟器环境干扰极大——微信开发者工具里 platform 是 "devtools",鸿蒙设备可能返回空字符串,H5 下又可能是 "web",根本不可靠。
- 要调用平台专属 API(如
wx.login()、plus.runtime.getProperty())→ 必须用/* #ifdef MP-WEIXIN */或/* #ifdef APP-PLUS */ - 要加载不同样式文件或 JS 模块 → 条件编译包裹 import 或 class 名
- 需要做平台级灰度开关(如只对小程序开启新接口)→ 编译期隔离最安全
- 写在
export default外部的条件编译会被整个模块跳过,务必紧贴代码,中间不能有空行或其它注释
platform 字段的真实用途和常见误判
platform 是运行时设备平台标识,只适合判断「底层设备类型」,比如要不要启用震动、是否支持 getBatteryInfo。但它不是「目标平台」:H5 页面里它可能是 "web",微信小程序真机上可能是 "android"(因为跑在安卓 WebView 里),而纯血鸿蒙设备却可能返回 "harmony" 或空。
- 错误写法:
if (uni.getSystemInfoSync().platform === 'ios') { /* 调用微信登录 */ }→ 微信开发者工具里也成立,但 H5 或支付宝小程序里会误入 - 正确组合:
uni.getSystemInfoSync().platform === 'ios' && uni.getSystemInfoSync().uniPlatform === 'app-plus'才表示「iOS 原生 App」 - 鸿蒙识别必须加
osName:先uni.canIUse('getDeviceInfoSync'),再取uni.getDeviceInfoSync()?.osName === 'harmony' -
uniPlatform字段才反映编译目标(如"mp-weixin"、"h5"),但它在 H5 和小程序中都存在,不能单独用于路由分发
为什么 $mp.platform 不推荐作为主判断依据
$mp 是一个非标准全局对象,只在部分版本的 uni-app 中注入,且行为不稳定:H5 环境下常为 undefined,App 平台不提供,微信小程序基础库低版本可能未定义 $mp.platform。更关键的是,它和 process.env.NODE_ENV 一样,属于构建时静态变量,无法感知运行时动态上下文(比如 web-view 嵌套页、分包加载后环境变化)。
- 它没有统一文档保障,不同 HBuilderX 版本表现不一致
- 在
onLaunch里访问可能因初始化顺序问题拿到undefined - 若需 fallback,优先用
uni.getAccountInfoSync()?.miniProgram?.envVersion(仅小程序)或uni.getSystemInfoSync().uniPlatform(多端通用) - 别把它和
__UNI_MP_VERSION混用:__UNI_MP_VERSION只在小程序平台存在,且所有小程序平台都定义它,无法区分微信/支付宝
真正难的不是写对一行条件编译,而是意识到「平台」这个词在 uni-app 里有至少三层含义:编译目标(H5)、运行容器(web)、设备系统(harmony)。选错维度,后续所有适配都会漂移。尤其在混合方案(如小程序转 App)或鸿蒙深度兼容场景下,单字段判断几乎必踩坑。











