每个端有每个端的特点,有的能被抹平,有的不可能被抹平。
注意:跨端,不是把web的习惯迁移到全平台。而是按照uni的写法,然后全平台使用。
非H5端不支持*选择器;
body的元素选择器请改为page,同样,div和ul和li等改为view、span和font改为text、a改为navigator、img改为image...
非H5端默认并未启用 scoped,如需要隔离组件样式可以在 style 标签增加 scoped 属性,H5端为了隔离页面间的样式默认启用了 scoped
vue页面在App端,默认是被系统的webview渲染的(不是手机自带浏览器,是rom的webview),在较老的手机上,比如Android4.4、5.0或iOS8,很多css是不支持的,所以不要使用太新的css,会导致界面异常。
注意这不意味着不能使用flex,Android4.4也支持flex,只是不要使用太新的css。
可以找Android4.4手机或使用pc模拟器实际测试下,大多数国产Android模拟器都是4.4或5.0。
从 uni-app 2.5.3 起,Android端支持引入腾讯x5浏览器内核,可以抹平低端Android的浏览器兼容性问题,详见x5使用指南 (opens new window)
小程序不存在浏览器兼容问题,它自带了一个很大的Webview。所以如果你的H5和小程序界面正常,而Android低端机App界面异常,且App没有使用x5引擎,那基本就可以判定是因为css兼容性。
app端nvue页面,不存在浏览器兼容问题,它自带一个统一的原生渲染引擎,不依赖webview。
Android4.4对应的webview是chrome37。各端浏览器内核的详情查阅,参考:关于手机webview内核、默认浏览器、各家小程序的渲染层浏览器的区别和兼容性 (opens new window)
如果你的代码没有直接使用这些,那很可能是引入的三方库使用了这些。如果是后者,去插件市场 (opens new window)搜索替代方案。要知道非H5端的js是运行在一个独立的js core或v8下,并不是运行在浏览器里。
从HBuilderX 2.6起,App端新增了renderjs,这是一种运行在视图层的js,vue页面通过renderjs可以操作浏览器对象,进而可以让基于浏览器的库直接在uni-app的App端运行,诸如echart、threejs,详见:renderjs
url(//alicdn.net)
等路径,改为url(https://alicdn.net)
,因为在App端//是file协议vue页面在App端的渲染引擎默认是系统webview(不是手机自带浏览器,是rom的webview),在较老的手机上,比如Android4.4、5.0或iOS8,一些新出的css语法是不支持的。注意这不意味着不能使用flex,Android4.4也支持flex,只是不要使用太新的css。可以找Android4.4手机或使用pc模拟器实际测试下,大多数国产Android模拟器都是4.4或5.0。
小程序不存在浏览器兼容问题,它内置了几十M自己的定制webview。所以如果你的H5和小程序界面正常,而App界面异常,大多是因为css兼容性。
解决这类问题:
uni-app
基于Vue 2.0
实现,开发者需注意Vue 1.0 -> 2.0 的使用差异,详见从 Vue 1.x 迁移 (opens new window)
data 属性必须声明为返回一个初始数据对象的函数;否则页面关闭时,数据不会自动销毁,再次打开该页面时,会显示上次数据
//正确用法,使用函数返回对象
data() {
return {
title: 'Hello'
}
}
//错误写法,会导致再次打开页面时,显示上次数据
data: {
title: 'Hello'
}
在微信小程序端,uni-app
将数据绑定功能委托给Vue
,开发者需按Vue 2.0
的写法实现数据绑定,不支持微信小程序的数据绑定写法,故如下写法不支持:
<view id="item-{{id}}"></view>
需修改为:
<view v-bind:id="'item-' + id "></view>
你之前可能习惯自由的web开发,但目前各家小程序都有很多限制。 当然限制是为了在框架层更好的优化用户体验,所以小程序的体验要优于web。 并且这些限制只是写法的限制,并不影响功能。 如果你做过微信小程序开发,对这些限制应该已经很了解了。如果没有做过小程序,请仔细阅读本节。
uni-app
基于Vue 2.0
实现,开发者需注意Vue 1.0 -> 2.0 的使用差异,详见从 Vue 1.x 迁移 (opens new window)H5 发布到服务器注意:
manifest.json
文件内编辑 h5 节点,router 下增加 base 属性为 html5
unpackage/dist/build/h5
目录找到出的资源,部署服务器(或者使用本地服务器预览),如需部署到相对路径(支持本地file协议打开)参考:https://ask.dcloud.net.cn/article/37432。引用第三方 js 的方式:
manifest.json
文件编辑 h5 节点的 template 属性,填写 html 模版路径,在 html 模版里面可以使用 script 的方式引入三方的 js,如下示例是加了百度统计的 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 (opens new window)
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 需要连接谷歌服务器。
组件内(页面除外)不支持 onLoad
、onShow
等页面生命周期。
为避免和内置组件冲突,自定义组件请加上前缀(但不能是 u 和 uni)。比如可使用的自定义组件名称:my-view
、m-input
、we-icon
,例如不可使用的自定义组件名称:u-view
、uni-input
,如果已有项目使用了可能造成冲突的名称,请修改名称,另外微信小程序下自定义组件名称不能以 wx 开头。
各家小程序的浏览器内核不同,可能会造成css兼容性问题,更多细节参考:https://ask.dcloud.net.cn/article/1318 (opens new window)
微信(可以使用virtualHost配置)/QQ/百度/字节跳动这四家小程序,自定义组件在渲染时会比App/H5端多一级节点,在写样式时需要注意:
flex
布局时,直接给自定义组件的父元素设置为display:flex
不能影响到自定义组件内部的根节点,需要设置当前自定义组件为display:flex
才可以。支付宝小程序不会插入节点,不存在如上问题。
小程序工具提示vendor.js
过大,已经跳过es6向es5转换。这个转换问题本身不用理会,因为vendor.js
已经是es5的了。
关于体积控制,参考如下:
HBuilderX
创建的项目勾选运行-->运行到小程序模拟器-->运行时是否压缩代码
cli
创建的项目可以在package.json
中添加参数--minimize
,示例:"dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize"
showLoading
是不透传的,也就是说 loading
显示的时候无法点击页面内容。@
符号。dataType
进行处理,如果不符合规范则会抛出错误,而不是按照原格式返回。canvas
组件的标识是 id
,而不是 canvas-id
。目前还未进行处理,所以需要主动添加 id 属性。1rpx
,需要直接用 1px
。scoped
。map
组件在开发工具上预览效果不对,但是手机上是对的。getSystemInfo
获取到的 windowHeight
在模拟器中值不正确,真机预览是正确的。v-if
和 v-for
不可在同一标签下同时使用。template
标签,这会导致部分选择器对应的样式匹配不上。<se-video></se-video>
<se-...></se-...>
为360平台专有组件,不能跨平台,需要条件编译 mp-360
pages 配置"globalStyle": {
"mp-360": {
"navigationStyle": "custom" // 去掉uni-app header,使用360小程序header
}
},
uni.login(OBJECT)
,暂时使用条件编译,参考文档 https://developer.huawei.com/consumer/cn/doc/development/quickApp-References/webview-api-hwaccount (opens new window)uni.login(OBJECT)
sign放到项目根目录,编译后自动拷贝到 .quickapp/sign,每次编译完成时会删除.quickapp,避免证书丢失