1.1 跨端的真问题与平台版图


1.1 跨端的真问题与平台版图

本节导读:跨端的难度不在"多写几套代码",而在差异藏在宿主、渲染、包管理、审核四个不同层面。本节把平台版图铺开,为整册的"罗盘"提供需要指路的全部航段;读完后再看 1.2 的条件编译,你会明白它每一处设计对应的是哪一层差异。

从一个真实场景切入

假设你负责一个会员积分商城:产品经理要求微信里能打开、浏览器里能打开、应用商店里能下载。你会立刻撞上三个问题。第一,微信里最顺手的形态是小程序,而小程序跑在微信提供的 JavaScript 运行环境里,没有完整的浏览器对象;第二,浏览器里是标准 Web 页面,DOM、BOM 样样都有,却没有原生导航栏和推送;第三,应用商店要求原生 App,iOS 与 Android 的包格式、签名、上架流程完全不同。同样的业务逻辑,三种宿主给出了三套约束。跨端框架要解决的,就是把业务逻辑写一次、把这三套约束收敛成一套可管理的差异。

平台版图:先分清三大类宿主

uni-app 的目标平台可以归成三大类。小程序类包括微信、支付宝、字节跳动、百度、QQ、快手、京东等,特点是代码跑在超级 App 提供的运行时里,逻辑层与渲染层分离,包体积有硬性上限,发布要经过平台审核。H5 类即普通浏览器环境,拥有完整 DOM 能力,部署自由(发个静态资源就能上线),但没有原生壳。App 类分两种渲染路线:vue 页面走内置 WebView 渲染(配合原生导航与窗口机制),nvue 页面走原生排版引擎;App 端还拥有 plus 运行时,可以调用绝大多数系统能力。下面的矩阵把各端关键属性摊开对比。

图 1-1 平台版图对比矩阵

图 1-1 平台版图对比矩阵

差异落在哪几层

把矩阵读薄,差异集中在四层。宿主层:小程序没有 windowdocument,H5 都有;App 端多出 plus 运行时。渲染层:小程序的组件最终由原生或 WebView 混合渲染,部分 css 特性(如部分选择器)不生效;H5 css 能力最完整;App 的 nvue 页面只支持有限的 css 子集且默认 flex 布局。包管理层:微信小程序主包上限两兆、总体积也有上限,逼你做分包;H5 与 App 没有这种硬限制,但要关心首屏与安装包大小。发布层:小程序审核、应用商店审核、H5 自由部署,节奏与回滚能力完全不同。

一个直观的对照实验:同一段"获取屏幕宽度"的逻辑,三端写法各不相同。

// H5:直接读浏览器对象 const w1 = window.innerWidth; // 小程序:没有 window,走 uni 系统 API uni.getSystemInfo({ success(res) { const w2 = res.windowWidth; console.log('可用窗口宽度:', w2); } }); // App 端(vue 页面):可以走 uni API,也可以走 plus const w3 = plus.display ? plus.display.applicationWidth : uni.upx2px(750);

若把这些差异直接写进业务代码,项目很快会变成"if 平台"的沼泽。uni-app 的处理方式分两层:一层是把高频能力统一收敛到 uni. 前缀的 API 体系(第 6 章展开);另一层就是条件编译,负责收敛不了的、平台专属的那部分。

三个高频误判,各对应一层差异

把版图讲给团队听时,最容易收到三种反驳,每一种都值得当场拆穿。误判一:"H5 端有 window,写点 window 没关系。" 麻烦在于这段代码在编译期不会报错——条件编译不处理的部分会被原样带进每端产物,等微信用户点到那个页面,控制台才告诉你 window is not defined。正确姿势是把浏览器专属逻辑圈进条件编译,让它在别的端编译期就消失:

function pageWidth() { // #ifdef H5 return window.innerWidth; // #endif // #ifndef H5 return uni.getSystemInfoSync().windowWidth; // #endif }

误判二:"小程序反正是同一种东西,一套写法通吃。" 各家小程序的 API 命名、授权流程、包体积上限都不一致,微信的登录与字节的登录是两条流程;把它们当同一种宿主,测试阶段就会在各家工具里轮流翻车。误判三:"App 端就是个套壳浏览器。" vue 页面确实跑在 WebView 里,但 plus 运行时给它的能力远超网页——推送、文件系统、原生插件都是 H5 拿不到的;反过来 nvue 页面的样式子集也比网页苛刻得多。把 App 当 H5 写,多半在推送与离线场景还账。

三种误判的共同根源,是拿某一端的直觉代表所有端。版图铺开的意义就在这里:先承认差异分布在四层,再让条件编译逐层认领,而不是指望某一段"聪明的代码"自动适配一切。

版图的边界:哪些差异没法抹平

诚实地列出条件编译也无法消除的差异,比记住能消除的更重要。小程序的包体积上限不会消失,业务再小也要规划分包;iOS 上热更新受审核政策约束,动态化方案要留后路;H5 的跨域由后端与代理解决,客户端无能为力;各家小程序的授权弹窗文案、登录流程由平台方定义,只能逐家适配。判断一个需求能否跨端统一,标准不是"代码能不能写",而是"各端宿主给不给这个能力"——这句话值得贴在工位上。

评审环节怎么用这张版图

版图落到日常,最有用的场景是需求评审。产品说"分享出去领优惠券",你按四层过一遍:宿主层,微信端分享靠小程序卡片、H5 端靠复制链接、App 端走原生分享面板;渲染层与此无关;发布层,H5 的活动页随时能上,小程序的分享配置变更却要重新审核。评审时把这几个答案摆出来,排期与方案的分歧自然消解。反过来,若等到开发中期才发现某端能力缺位,返工的就不只是一个函数,而是交互方案本身。把"这个需求在四层各是什么表现"写成评审模板的固定一栏,是团队从这套版图里能拿走的最实在的东西。

本节要点回顾

  • 跨端差异分布在宿主、渲染、包管理、发布四层,逐层认领比笼统记"平台差异"有效;
  • 小程序类、H5 类、App 类三类宿主的能力边界,决定了哪些逻辑能统一、哪些必须分叉;
  • uni. API 收敛高频能力,条件编译处理平台专属部分,二者配合而非互替;
  • 包体积、审核政策、授权流程是三类宿主里最刚性的约束,架构设计要先把它们框进去。

下一节我们进入罗盘本体:条件编译到底怎么写、编译器拿到标记后做了什么。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U