做过 uniapp 的同学应该都有体会:一套代码跑在 H5、微信小程序、App 甚至各家小程序上,最头疼的不是写业务,而是「同一段样式在不同端表现不一致」。这篇文章整理我在多个上线项目里踩过的坑,聊聊多端适配真正有效的做法。
先想清楚:适配的边界在哪
多端适配不是追求像素级完全一致,而是保证功能可用、体验接近。我的原则是:能用统一方案解决的绝不分端写,必须分端的用条件编译隔离,且隔离点越少越好。
- 统一层:布局、逻辑、状态管理、请求封装
- 差异层:平台 API、生命周期、部分样式
尺寸适配:rpx 不是万能的
uniapp 的 rpx 以 750 设计稿为基准,小程序和 App 上表现良好,但 H5 端在宽屏下会被拉伸得很难看。我的做法是:
- 小程序 / App 直接用
rpx,省心 - H5 端用媒体查询限制最大宽度,或改用
rem+ 动态根字号 - 字体大小谨慎用 rpx,建议用
px或固定值,避免大屏字过大
/* H5 限制内容宽度 */
@media screen and (min-width: 768px) {
.container {
max-width: 750px;
margin: 0 auto;
}
}条件编译:分端逻辑的利器
uniapp 的条件编译是适配的核心工具,语法是 #ifdef / #ifndef / #endif。常见场景:
1. 平台专属 API
// #ifdef MP-WEIXIN
wx.login({ success: res => console.log(res.code) })
// #endif
// #ifdef H5
console.log('H5 端走自己的登录逻辑')
// #endif2. 样式差异
/* #ifdef H5 */
.btn { cursor: pointer; }
/* #endif */
/* #ifdef APP-PLUS */
.btn { padding-top: 20rpx; }
/* #endif */建议把条件编译尽量收敛到工具函数里,而不是散落在业务代码中。比如封装一个 platform.js,对外暴露统一方法,内部用条件编译处理差异。
平台 API 差异的封装策略
不同端的 API 名称、参数、回调形式都可能不同。我习惯用「适配层」模式:
// utils/storage.js
const storage = {
set(key, value) {
// #ifdef H5
localStorage.setItem(key, JSON.stringify(value))
// #endif
// #ifndef H5
uni.setStorageSync(key, value)
// #endif
}
}
export default storage这样业务层只调用 storage.set(),完全不用关心端差异。请求库、上传、支付、分享都建议这样包一层。
布局与组件的通用技巧
- 优先用
flex布局,兼容性最好,避免浮动和绝对定位混用 - 用
uni-app官方组件(view、text、image)而非 HTML 标签,跨端一致 - 安全区适配用
env(safe-area-inset-bottom),iOS 刘海屏必备 - 滚动用
scroll-view而非页面滚动,小程序端体验更稳 - 图片统一用
mode属性控制裁剪方式,避免各端默认行为不同
导航栏与状态栏适配
自定义导航栏时,状态栏高度各端不同。可以用 uni.getSystemInfoSync().statusBarHeight 获取,App 端还要考虑沉浸式。建议封装一个 NavBar 组件,内部处理状态栏高度和胶囊位置。
const sysInfo = uni.getSystemInfoSync()
const statusBarHeight = sysInfo.statusBarHeight || 0调试与真机验证
模拟器永远骗你,真机才是真相。
我的习惯是每完成一个模块,至少在 H5、微信开发者工具、iOS 真机三端各跑一遍。重点看:布局错位、字体渲染、点击区域、滚动性能。App 端还要关注键盘弹起、返回键、权限弹窗等系统行为。
总结
多端适配的本质是抽象共性、隔离差异。把平台差异收敛到适配层,业务代码保持纯净,维护成本会大幅下降。不要一开始就想着覆盖所有端,先把主力端跑通,再逐步兼容,这样迭代最稳。
评论 (0)
还没有评论,快来抢沙发吧~