# 多端适配方案 ## 一、平台差异处理 ### 1.1 条件编译 使用 UniApp 的条件编译处理不同平台的差异: ```javascript // #ifdef MP-WEIXIN // 微信小程序特有代码 wx.login() // #endif // #ifdef H5 // H5特有代码 window.location.href = '/login' // #endif // #ifdef APP-PLUS // App特有代码 plus.runtime.restart() // #endif ``` ### 1.2 平台判断工具 使用封装的平台判断工具: ```javascript import { getPlatform, isMiniProgram, isH5, isApp } from '@/utils/platform' if (isMiniProgram()) { // 小程序端逻辑 } else if (isH5()) { // H5端逻辑 } else if (isApp()) { // App端逻辑 } ``` ## 二、API 适配 ### 2.1 统一 API 封装 对不同平台的 API 进行统一封装: ```javascript // 跨端导航 export const navigateTo = (url, params = {}) => { const query = Object.keys(params) .map(key => `${key}=${encodeURIComponent(params[key])}`) .join('&') const fullUrl = query ? `${url}?${query}` : url uni.navigateTo({ url: fullUrl }) } // 跨端存储 export const setStorage = (key, value) => { // #ifdef MP-WEIXIN wx.setStorageSync(key, value) // #endif // #ifdef H5 localStorage.setItem(key, JSON.stringify(value)) // #endif // #ifdef APP-PLUS plus.storage.setItem(key, JSON.stringify(value)) // #endif } ``` ### 2.2 第三方登录适配 不同平台的第三方登录实现: ```javascript // 微信登录 export const wechatLogin = () => { return new Promise((resolve, reject) => { // #ifdef MP-WEIXIN wx.login({ success: (res) => { resolve(res.code) }, fail: reject }) // #endif // #ifdef H5 // H5微信授权登录 const appId = 'YOUR_APP_ID' const redirectUri = encodeURIComponent(window.location.href) window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_userinfo#wechat_redirect` // #endif }) } ``` ## 三、样式适配 ### 3.1 尺寸单位适配 - **小程序端**:使用 `rpx`(750rpx = 屏幕宽度) - **H5端**:使用 `rem` 或 `vw` - **App端**:使用 `rpx` 或 `upx` ```scss // 统一使用 rpx,UniApp 会自动转换 .container { width: 750rpx; padding: 30rpx; font-size: 28rpx; } ``` ### 3.2 安全区域适配 处理刘海屏、底部安全区域: ```scss .page { // 顶部安全区域 padding-top: constant(safe-area-inset-top); padding-top: env(safe-area-inset-top); // 底部安全区域 padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); } ``` ### 3.3 状态栏高度适配 ```javascript // 获取状态栏高度 const systemInfo = uni.getSystemInfoSync() const statusBarHeight = systemInfo.statusBarHeight // 在样式中使用 const navBarHeight = statusBarHeight + 44 // 44为导航栏高度 ``` ## 四、功能适配 ### 4.1 分享功能 ```javascript // 小程序分享 // #ifdef MP-WEIXIN onShareAppMessage() { return { title: '分享标题', path: '/pages/index/index', imageUrl: '/static/share.png' } } // #endif // H5分享 // #ifdef H5 const shareToWechat = () => { // 调用微信 JS-SDK wx.updateAppMessageShareData({ title: '分享标题', desc: '分享描述', link: window.location.href, imgUrl: 'https://example.com/share.png' }) } // #endif ``` ### 4.2 支付功能 ```javascript // 统一支付接口 export const pay = (orderInfo) => { return new Promise((resolve, reject) => { // #ifdef MP-WEIXIN wx.requestPayment({ timeStamp: orderInfo.timeStamp, nonceStr: orderInfo.nonceStr, package: orderInfo.package, signType: 'MD5', paySign: orderInfo.paySign, success: resolve, fail: reject }) // #endif // #ifdef H5 // H5微信支付 WeixinJSBridge.invoke('getBrandWCPayRequest', orderInfo, (res) => { if (res.err_msg === 'get_brand_wcpay_request:ok') { resolve(res) } else { reject(res) } }) // #endif // #ifdef APP-PLUS // App支付 plus.payment.request('wxpay', orderInfo, resolve, reject) // #endif }) } ``` ### 4.3 定位功能 ```javascript // 获取位置 export const getLocation = () => { return new Promise((resolve, reject) => { uni.getLocation({ type: 'gcj02', success: (res) => { resolve({ latitude: res.latitude, longitude: res.longitude }) }, fail: (err) => { // #ifdef H5 // H5使用浏览器定位API if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( (position) => { resolve({ latitude: position.coords.latitude, longitude: position.coords.longitude }) }, reject ) } else { reject(new Error('浏览器不支持定位')) } // #endif // #ifndef H5 reject(err) // #endif } }) }) } ``` ## 五、性能适配 ### 5.1 小程序分包 ```json { "pages": [ "pages/index/index", "pages/user/index" ], "subPackages": [ { "root": "subPackages/order", "pages": [ "list/index", "detail/index" ] }, { "root": "subPackages/product", "pages": [ "list/index", "detail/index" ] } ], "preloadRule": { "pages/index/index": { "network": "all", "packages": ["subPackages/order"] } } } ``` ### 5.2 图片懒加载 ```vue ``` ### 5.3 长列表优化 ```vue ``` ## 六、兼容性处理 ### 6.1 API 兼容性检查 ```javascript // 检查API是否支持 if (uni.canIUse('getSystemInfoSync')) { const systemInfo = uni.getSystemInfoSync() } // 版本号比较 const compareVersion = (v1, v2) => { const arr1 = v1.split('.') const arr2 = v2.split('.') const len = Math.max(arr1.length, arr2.length) for (let i = 0; i < len; i++) { const num1 = parseInt(arr1[i] || 0) const num2 = parseInt(arr2[i] || 0) if (num1 > num2) return 1 if (num1 < num2) return -1 } return 0 } // 使用示例 const systemInfo = uni.getSystemInfoSync() if (compareVersion(systemInfo.SDKVersion, '2.10.0') >= 0) { // 支持新API } ``` ### 6.2 样式兼容性 ```scss // 使用 CSS 变量实现主题切换 :root { --primary-color: #1890ff; --text-color: #333; } .button { background-color: var(--primary-color); color: var(--text-color); } // 使用 autoprefixer 自动添加前缀 .flex-container { display: flex; // 自动添加 -webkit-flex } ``` ## 七、调试技巧 ### 7.1 多端调试 - **微信小程序**:使用微信开发者工具 - **H5**:使用浏览器开发者工具 - **App**:使用 HBuilderX 真机调试 ### 7.2 日志输出 ```javascript // 开发环境输出日志 if (process.env.NODE_ENV === 'development') { console.log('调试信息:', data) } // 使用条件编译输出平台信息 // #ifdef MP-WEIXIN console.log('当前平台:微信小程序') // #endif ``` ### 7.3 错误监控 ```javascript // 全局错误捕获 uni.onError((error) => { console.error('全局错误:', error) // 上报到错误监控平台 }) // 网络错误监控 uni.onNetworkStatusChange((res) => { if (!res.isConnected) { uni.showToast({ title: '网络已断开', icon: 'none' }) } }) ```