Appearance
UniApp 跨端要点
每个端有每个端的特点,有的能被抹平,有的不可能被抹平。
注意:跨端,不是把 web 的习惯迁移到全平台。而是按照 uni 的写法,然后全平台使用。
1. H5 正常但 App 异常的可能性
css 异常:
不支持的选择器
非 H5 端不支持
*选择器。body的元素选择器请改为page,同样,div、ul、li等改为view、span。font改为text,a改为navigator、img改为image……组件和页面样式相互影响
非 H5 端默认并未启用
scoped,如需要隔离组件样式可以在style标签增加scoped属性,H5 端为了隔离页面间的样式默认启用了scoped。webview 浏览器兼容性
vue 页面在 App 端,默认是被系统的 webview 渲染的(不是手机自带浏览器,是 rom 的 webview),在较老的手机上,比如 Android4.4、5.0 或 iOS8,很多 css 是不支持的,所以不要使用太新的 css,会导致界面异常。
注意这不意味着不能使用
flex,Android 4.4 也支持flex,只是不要使用太新的 css。可以找 Android4.4 手机或使用 pc 模拟器实际测试下,大多数国产 Android 模拟器都是 4.4 或 5.0。
从 uni-app 2.5.3 起,Android 端支持引入腾讯 x5 浏览器内核,可以抹平低端 Android 的浏览器兼容性问题,详见 x5 使用指南。
小程序不存在浏览器兼容问题,它自带了一个很大的 webview。所以如果你的 H5 和小程序界面正常,而 Android 低端机 App 界面异常,且 App 没有使用 x5 引擎,那基本就可以判定是因为 css 兼容性。
app 端 nvue 页面,不存在浏览器兼容问题,它自带一个统一的原生渲染引擎,不依赖 webview。
Android 4.4 对应的 webview 是 chrome37。各端浏览器内核的详情查阅,参考:关于手机 webview 内核、默认浏览器、各家小程序的渲染层浏览器的区别和兼容性。
原生组件层级问题,H5 没有原生组件概念问题,非 H5 端有原生组件并引发了原生组件层级高于前端组件的概念,要遮挡
video、map等原生组件,请使用cover-view组件。
使用了非 H5 端不支持的 API,小程序和 App 的 js 运行在 jscore 下而不是浏览器里,没有浏览器专用的 js 对象,比如
document、xmlhttp、cookie、window、location、navigator、localstorage、websql、indexdb、webgl等对象。如果你的代码没有直接使用这些,那很可能是引入的三方库使用了这些。如果是后者,去插件市场搜索替代方案。要知道非 H5 端的 js 是运行在一个独立的 js core 或 v8 下,并不是运行在浏览器里。
从 HBuilderX 2.6 起,App 端新增了 renderjs,这是一种运行在视图层的 js,vue 页面通过 renderjs 可以操作浏览器对象,进而可以让基于浏览器的库直接在 uni-app 的 App 端运行,诸如 echart、threejs,详见:renderjs。
使用了非 H5 端不支持的 vue 语法,受小程序自定义组件限制的写法,详见。
不要在引用组件的地方在组件属性上直接写
style="xx",要在组件内部写样式。url(//alicdn.net)等路径,改为url(https://alicdn.net),因为在 App 端//是 file 协议。很多人在 H5 端联网时使用本地测试服务地址 (
localhost或127.0.0.1),这样的联网地址手机 App 端是无法访问的,请使用手机可访问的 IP 进行联网。
2. H5 正常但小程序异常的可能性
- 同上;
- v-html 在 h5 和 app-vue 均支持,但小程序不支持;
- 小程序要求连接的网址都要配白名单;
3. 小程序正常但 App 异常的可能性
vue 页面在 App 端的渲染引擎默认是系统 webview(不是手机自带浏览器,是 rom 的 webview),在较老的手机上,比如 Android4.4、5.0 或 iOS8,一些新出的 css 语法是不支持的。注意这不意味着不能使用 flex,Android4.4 也支持 flex,只是不要使用太新的 css。可以找 Android4.4 手机或使用 pc 模拟器实际测试下,大多数国产 Android 模拟器都是 4.4 或 5.0。
小程序不存在浏览器兼容问题,它内置了几十兆自己的定制 webview。所以如果你的 H5 和小程序界面正常,而 App 界面异常,大多是因为 css 兼容性。
解决这类问题:
放弃老款手机支持。
不用使用太新的 css 语法,可以在 caniuse 查询。
从 uni-app 2.5.3 起,Android 端支持引入腾讯 x5 浏览器内核,可以抹平低端 Android 的浏览器兼容性问题,详见 x5 使用指南。
4. 小程序或 App 正常,但 H5 异常的可能性
在 uni-app 2.4.7 以前,H5 端不支持微信小程序自定义组件,即
wxcomponents下的组件,此时可能产生兼容问题。从 2.4.7 起,H5 也支持微信自定义组件,不再存在这这方面兼容问题。App 端使用了 App 特有的 API 和功能,比如 plus、Native.js、subNVue、原生插件等
使用了小程序专用的功能,比如微信卡券、小程序插件、微信小程序云开发。对于云开发,建议使用可跨端的 uniCloud。
5. App 正常,小程序、H5 异常的可能性
代码中使用了 App 端特有的 plus、Native.js、subNVue、原生插件等功能。
6. 使用 Vue.js 的注意
uni-app 基于 Vue 2.0 实现,开发者需注意 Vue 1.0 -> 2.0 的使用差异,详见从 Vue 1.x 迁移。
data属性必须声明为返回一个初始数据对象的函数;否则页面关闭时,数据不会自动销毁,再次打开该页面时,会显示上次数据:JavaScript// 正确用法,使用函数返回对象 data() { return { title: 'Hello' } } // 错误写法,会导致再次打开页面时,显示上次数据 data: { title: 'Hello' }在微信小程序端,uni-app 将数据绑定功能委托给 Vue,开发者需按 Vue 2.0 的写法实现数据绑定,不支持微信小程序的数据绑定写法,故如下写法不支持:
HTML<view id="item-{{id}}"></view>需修改为:
HTML<view v-bind:id="'item-' + id "></view>
7. 区别于传统 web 开发的注意
你之前可能习惯自由的 web 开发,但目前各家小程序都有很多限制。当然限制是为了在框架层更好的优化用户体验,所以小程序的体验要优于 web。并且这些限制只是写法的限制,并不影响功能。如果你做过微信小程序开发,对这些限制应该已经很了解了。如果没有做过小程序,请仔细阅读本节。
JS 注意
非 H5 端,不能使用浏览器自带对象,比如
document、window、localstorage、cookie等,更不能使用 jquery 等依赖这些浏览器对象的框架。因为各家小程序快应用都不支持这些对象。没有这些浏览器自带对象并不影响业务开发,uni 提供的 api 足够完成业务。
uni 的 api 在编译到 web 平台运行时,其实也会转为浏览器的 js api。
Tag 注意
uni-app 的 tag 同小程序的 tag,和 HTML 的 tag 不一样,比如
div要改成view,span要改成text、a要改成navigator。出于降低 h5 应用向 uni-app 迁移成本的考虑,写成
div、span也可以运行在 app 和小程序上,因为 uni-app 编译器会把这些 HTML 标签编译为小程序标签。但仍然建议养成新习惯。Css 注意
虽然大部分 css 样式在微信小程序和 app 中都可以支持,但推荐使用 flex 布局模型,这种布局更灵活高效且支持更多平台(比如 nvue、快应用只支持 flex 布局)。
单位方面,uni-app 默认为
rpx。这是一种可跨端的通用单位详见。工程目录注意
页面文件:放到
pages目录下;推荐方案:新建一个页面目录,然后创建一个目录同名的.vue文件,如/pages/list/list.vue,接着在pages.json里完成注册。这与小程序的策略相同。自定义组件:放到
component目录。静态资源:如图片,固定放到
static目录下。这是 webpack 的规则。数据绑定方式的注意
uni-app 基于 Vue 2.0 实现,开发者需注意 Vue 1.0 -> 2.0 的使用差异,详见从 Vue 1.x 迁移。
每个页面支持使用原生
title,首页支持使用原生底部tab,这些是要在pages.json里配置,这些并不是 vue 页面的一部分。当然 vue 里的 js api 也可以动态修改原生title。虽然使用 vue,但在 app 和小程序里,不是 spa 而是 mpa。
位置坐标系统一为国测局坐标系 gcj02,这种坐标系可以被多端支持。老版 5+ 的百度定位和百度地图使用的是百度私有坐标系 bd09ll,这种坐标系需要转换。新版 uni-app 里的百度地图已经默认改为 gcj02。高德地图不受影响,一直是 gcj02。
8. H5 开发注意
H5 发布到服务器注意:
配置发行后的路径(发行在网站根目录可不配置),比如发行网站路径是
www.xxx.com/html5,在manifest.json文件内编辑 h5 节点,router下增加base属性为html5:
图 8.1 - 配置发行后的路径 点击菜单 “发行 -> H5”。
在当下项目下的
unpackage/dist/build/web目录找到输出的资源,部署服务器(或者使用本地服务器预览),如需部署到相对路径(Vue2 项目支持本地 file 协议打开)参考:https://ask.dcloud.net.cn/article/37432。从 HBuilderX 4.06 开始,为了统一概念,编译目录从 h5 调整为 web,开发者的 CI/CD 流程需要同步进行更新。
引用第三方 js 的方式:
通过 npm 引入(通过条件编译,只有是 h5 平台才
import相应的库)。在
manifest.json文件编辑 h5 节点的template属性,填写 html 模版路径,在 html 模版里面可以使用 script 的方式引入三方的 js,如下示例是加了百度统计的 html 模板部分代码,模版全部代码可参考:自定义模板。HTML<!-- ... --> <body> <noscript> <strong>Please enable JavaScript to continue.</strong> </noscript> <div id="app"></div> <!-- built files will be auto injected --> <script> var _hmt = _hmt || []; (function () { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?xxxxxx"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script> </body> <!-- ... -->
H5 版 uni-app 全支持 vue 语法,所以可能造成部分写法在 H5 端生效,在小程序或 App 端不生效。
H5 校验了更严格的 vue 语法,有些写法不规范会报警,比如:data 后面写对象会报警,必须写 function;不能修改 props 的值;组件最外层 template 节点下不允许包含多个节点等。
编译为 H5 版后生成的是单页应用(SPA)。
如果遇到跨域造成 js 无法联网,注意网络请求(request、uploadFile、downloadFile 等)在浏览器存在跨域限制,解决方案有详见:https://ask.dcloud.net.cn/article/35267。
APP 和小程序的导航栏和 tabbar 均是原生控件,元素区域坐标是不包含原生导航栏和 tabbar 的;而 H5 里导航栏和 tabbar 是 div 模拟实现的,所以元素坐标会包含导航栏和 tabbar 的高度。为了优雅的解决多端高度定位问题,uni-app 新增了 2 个 css 变量:--window-top 和 --window-bottom,这代表了页面的内容区域距离顶部和底部的距离。举个实例,如果你想在原生 tabbar 上方悬浮一个菜单,之前写 bottom:0。这样的写法编译到 h5 后,这个菜单会和 tabbar 重叠,位于屏幕底部。而改为使用 bottom:var(--window-bottom),则不管在 app 下还是在 h5 下,这个菜单都是悬浮在 tabbar 上浮的。这就避免了写条件编译代码。当然仍然也可以使用 H5 的条件编译处理界面的不同。
CSS 內使用 vh 单位的时候注意 100vh 包含导航栏,使用时需要减去导航栏和 tabBar 高度,部分浏览器还包含浏览器操作栏高度,使用时请注意。
正常支持 rpx,px 是真实物理像素。暂不支持通过设 manifest.json 的 "transformPx": true,把 px 当动态单位使用。
使用罗盘、地理位置、加速计等相关接口需要使用 https 协议,本地预览(localhost)可以使用 http 协议。
PC 端 Chrome 浏览器模拟器设备测试的时候,获取位置 API 需要连接谷歌服务器。
vue2 组件内(页面除外)不支持 onLoad、onShow 等页面生命周期,vue3 请使用组合式 api 监听。
为避免和内置组件冲突,自定义组件请加上前缀(但不能是 u 和 uni)。比如可使用的自定义组件名称:my-view、m-input、we-icon,例如不可使用的自定义组件名称:u-view、uni-input,如果已有项目使用了可能造成冲突的名称,请修改名称,另外微信小程序下自定义组件名称不能以 wx 开头。
vue3 开发阶段不会自动处理语法兼容问题,如果在低版本浏览器上运行,需要自行处理,可参考详情。
9. 小程序开发注意
9.1. 文件命名
vue3 项目,页面或组件目录下,不能使用与 vue、nvue 同名的 js、ts 文件。
小程序端 vue 文件会被编译为同名的 js、json、wxml、wxss 文件,如果存在同名 js、ts 文件,会导致冲突。
9.2. 各家小程序实现机制不同,可能存在的平台兼容问题
浏览器内核差异
各家小程序的浏览器内核不同,可能会造成 css 兼容性问题,更多细节参考:https://ask.dcloud.net.cn/article/1318。
自定义组件渲染差异
微信(可以使用 virtualHost 配置)/ QQ / 百度 / 抖音这四家小程序,自定义组件在渲染时会比 App/H5 端多一级节点,在写样式时需要注意:
使用 flex 布局时,直接给自定义组件的父元素设置为
display: flex不能影响到自定义组件内部的根节点,需要设置当前自定义组件为display: flex才可以。在自定义组件内部设置根元素高度为
100%,不能撑满自定义组件父元素。需要同时设置当前自定义组件高度为100%才可以。
支付宝小程序默认启用了 virtualHost 配置不会插入节点,一般不存在如上问题。
9.3. vendor.js 过大的处理方式
小程序工具提示 vendor.js 过大,已经跳过 es6 向 es5 转换。这个转换问题本身不用理会,因为 vendor.js 已经是 es5 的了。
关于体积控制,参考如下:
使用运行时代码压缩:
HBuilderX 创建的项目,勾选 “运行 -> 运行到小程序模拟器 -> 运行时是否压缩代码”。
cli 创建的项目可以在
package.json中添加参数--minimize,示例:PowerShell"dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize"
使用分包优化,关于分包优化的说明。
9.4. 微信小程序开发注意
建议关注微信小程序当前 bug 列表,对已知 Bug,想办法避让。
ios 真机调试时,需要开启 “详情” 下 “本地设置” 的 “上传代码时自动压缩脚本文件” 选项,否则会报错。
9.5. 支付宝小程序开发注意
showLoading是不透传的,也就是说loading显示的时候无法点击页面内容。文件名或文件夹名中不允许出现
@符号。网络请求返回的数据会严格按照
dataType进行处理,如果不符合规范则会抛出错误,而不是按照原格式返回。canvas组件的标识是id,而不是canvas-id。目前还未进行处理,所以需要主动添加id属性。目前测试的结果,导航栏只有设置背景颜色为
#FFF(FFF)时才会变成黑色文字。支付宝小程序的导航栏是支持透明渐变效果的,后面会提供相关的配置。
使用伪元素做边框时,高度值不能用
1rpx,需要直接用1px。不支持 ECharts。
支付功能模拟不了,需要真机测试。