uni-app多端复用的核心限制在于平台API差异和渲染层隔离,需通过语句级条件编译、路径别名分离、组件能力抽象及原生接口运行时加载来精准适配。

uni-app 多端复用的核心限制在哪
不是所有代码都能直接跨 App 和小程序运行,根本卡点在平台 API 差异和渲染层隔离。比如 uni.chooseImage 在微信小程序返回 tempFilePaths,而在 App 端(尤其是 iOS)可能返回 localFilePath 或完整 file:// 路径;再如 uni.getSystemInfoSync() 的返回字段,App 端多出 model、platform,小程序则带 SDKVersion —— 这些差异不处理,运行时就报 undefined is not an object。
条件编译必须精确到语句级,不能只包整个函数
很多人把整段逻辑用 #ifdef MP-WEIXIN 包起来,结果 App 端漏掉初始化、小程序端多执行了原生模块调用。真正安全的做法是把判断下沉到最小可执行单元:
- API 调用前加平台判断:
if (process.env.UNI_PLATFORM === 'mp-weixin') { uni.openLocation(...) } else if (process.env.UNI_PLATFORM === 'app-plus') { uni.openLocation(...) } - 路径别名要拆开:图片资源用
@/static/img/logo@mp.png和@/static/img/logo@app.png,构建时自动替换 - 样式中慎用
/* #ifdef H5 */,优先用 CSS 变量或 class 控制,避免样式表被整块剔除导致布局错乱
自定义组件如何做到「一次写、两端跑」
关键在剥离平台强依赖。比如一个「分享按钮」组件,不能在 onLoad 里直接调用 uni.showShareMenu(App 不支持),而应:
- 把分享逻辑抽成
shareHandler方法,在父页面按平台注入:shareHandler={platform === 'mp-weixin' ? wxShare : appShare} - 使用
props传递能力标识::can-share="!!uni.canIUse('showShareMenu'),让子组件决定是否渲染按钮 - 避免在组件
created钩子中访问uni.getProvider,该 API 在小程序端同步返回,在 App 端异步回调 —— 容易引发竞态
App 独有功能(如原生插件、蓝牙)怎么不污染小程序代码
最稳妥的方式是「接口抽象 + 运行时加载」。不要在通用业务文件里 import uni.requireNativePlugin('xxx'),而是:
- 建
plugins/native-bridge.js,导出统一接口:export const scanBluetooth = () => { ... } - 内部用
process.env.UNI_PLATFORM === 'app-plus'分支加载原生能力,其他平台返回 Promise.reject(new Error('not supported')) - 业务层只调用
scanBluetooth(),错误统一用catch处理,不中断流程
这样小程序构建时不会打包原生插件,App 端也能按需加载,连摇树优化都省了。
复用的边界往往不在写了多少,而在删了多少——删掉那些“看起来能跑但其实靠运气”的兼容写法,比堆条件编译更可靠。











