🔀 Taro 从零到一(八):多端适配与条件编译
系列导读:Taro 的核心价值在于多端,但各平台总有差异。 本文教你用条件编译和运行时判断优雅处理多端差异。
📊 各平台主要差异
| 能力 | 微信 | 支付宝 | 抖音 | H5 |
|---|---|---|---|---|
| TabBar | 原生 | 原生 | 原生 | Taro 模拟 |
| 分享 | onShareAppMessage | onShareAppMessage | onShareAppMessage | Web Share API |
| 支付 | wx.requestPayment | my.tradePay | tt.pay | 自定义 |
| 登录 | wx.login | my.getAuthCode | tt.login | 自定义 |
| 扫码 | wx.scanCode | my.scan | tt.scanCode | ❌ |
🔧 1. 编译时条件编译
文件维度
src/
├── components/
│ └── ShareButton/
│ ├── index.tsx # 默认实现
│ ├── index.weapp.tsx # 微信小程序专用
│ ├── index.alipay.tsx # 支付宝专用
│ └── index.h5.tsx # H5 专用
Taro 编译时会自动选择对应平台的文件。 例如编译微信小程序时,
index.weapp.tsx优先于index.tsx。
代码块维度
// 环境变量判断
function LoginButton() {
const handleLogin = async () => {
if (process.env.TARO_ENV === 'weapp') {
// 微信登录
const { code } = await Taro.login()
await authApi.loginByWechat(code)
} else if (process.env.TARO_ENV === 'alipay') {
// 支付宝登录
const res = await Taro.login()
await authApi.loginByAlipay(res.authCode)
} else if (process.env.TARO_ENV === 'h5') {
// H5 跳转登录页
Taro.navigateTo({ url: '/pages/login/index' })
}
}
return <Button onClick={handleLogin}>登录</Button>
}
注释条件编译(推荐)
function PaymentButton({ orderId }: { orderId: string }) {
const handlePay = async () => {
/* #ifdef weapp */
// 仅在微信小程序中编译
const res = await Taro.requestPayment({
timeStamp: payInfo.timeStamp,
nonceStr: payInfo.nonceStr,
package: payInfo.package,
signType: 'MD5',
paySign: payInfo.paySign,
})
/* #endif */
/* #ifdef alipay */
// 仅在支付宝中编译
await Taro.tradePay({ tradeNO: payInfo.tradeNo })
/* #endif */
/* #ifdef h5 */
// 仅在 H5 中编译
window.location.href = payInfo.payUrl
/* #endif */
}
return <Button onClick={handlePay}>立即支付</Button>
}
🧩 2. 多端适配工具
// src/utils/platform.ts
import Taro from '@tarojs/taro'
// 当前平台
export const isWeapp = process.env.TARO_ENV === 'weapp'
export const isAlipay = process.env.TARO_ENV === 'alipay'
export const isH5 = process.env.TARO_ENV === 'h5'
export const isTt = process.env.TARO_ENV === 'tt'
// 获取系统信息
export function getSystemInfo() {
const info = Taro.getSystemInfoSync()
return {
platform: info.platform, // ios / android / devtools
screenWidth: info.screenWidth,
screenHeight: info.screenHeight,
statusBarHeight: info.statusBarHeight || 0,
safeArea: info.safeArea,
isIOS: info.platform === 'ios',
isAndroid: info.platform === 'android',
}
}
// 安全区域适配
export function getSafeAreaBottom(): number {
const info = Taro.getSystemInfoSync()
if (info.safeArea) {
return info.screenHeight - info.safeArea.bottom
}
return 0
}
// 使用
import { isWeapp, isH5 } from '@/utils/platform'
function ShareButton() {
// 微信小程序使用原生分享
if (isWeapp) {
return <Button openType="share">分享给好友</Button>
}
// H5 使用自定义分享
if (isH5) {
return (
<Button onClick={() => {
// 复制链接或调用 Web Share API
Taro.setClipboardData({ data: window.location.href })
Taro.showToast({ title: '链接已复制' })
}}>
分享链接
</Button>
)
}
return null
}
📱 3. 样式适配
// 导航栏高度适配
.custom-nav {
// 微信小程序自定义导航栏需要计算状态栏高度
padding-top: env(safe-area-inset-top);
}
// 底部安全区域(iPhone X 系列)
.bottom-bar {
padding-bottom: env(safe-area-inset-bottom);
}
// 多端样式差异
/* #ifdef weapp */
.page { background: #f5f5f5; }
/* #endif */
/* #ifdef h5 */
.page { background: #fff; max-width: 750px; margin: 0 auto; }
/* #endif */
🔌 4. 多端配置
// config/index.ts
const config = {
// H5 配置
h5: {
publicPath: '/',
devServer: { port: 10086 },
router: { mode: 'browser' }, // history 模式
},
// 微信小程序配置
mini: {
postcss: {
pxtransform: {
enable: true,
config: { designWidth: 750 },
},
},
miniCssExtractPluginOption: {
ignoreOrder: true,
},
},
}
✅ 本篇小结 Checklist
- 理解各平台的主要差异点
- 掌握文件维度条件编译(
.weapp.tsx) - 掌握注释条件编译(
#ifdef) - 会封装平台判断工具
- 处理样式适配(安全区域、导航栏)
下一篇预告:《小程序原生能力调用》
本文是「Taro 从零到一」系列第 8 篇,共 10 篇。