简体中文
新增于4.0版本
uni-app x 编译到web平台时,并非是与uni-app js引擎版一致。而是基于uts的统一规范,和编译到安卓端的一致性较高。
与App版相比,web版有几个较大的差别:
本文档会介绍与web和Android的差异及注意事项。
uni-app x编译到web端时遵循vue规范,目前有部分vue特性暂不支持。
不支持的特性如下
v-once
、v-memo
onPageScroll
、onReachBottom
生命周期部分支持的特性
defineMixin
函数定义mixin,不可直接使用对象字面量定义mixin自4.11版本起支持如下特性
defineOptions
、defineModel
、toValue
、toRef
、toRefs
、hasInjectionContext
使用refs获取内置组件实例时会获取到对应的Element,而不是vue组件实例。
<template>
<view ref="view"></view>
</template>
<script>
export default {
onReady() {
console.log(this.$refs['view']) // 此时获取到的是UniViewElement
}
}
</script>
为保证运行性能,app安卓端部分属性(如:$data、$refs)被转为了Map类型(安卓端map支持使用下标访问),而web端仍是普通对象或proxy。为保证多端代码一致,在使用这些属性时可以统一为下标访问。
<template>
<view></view>
</template>
<script>
export default {
data() {
return {
a: 1
}
},
onReady() {
console.log(this.$data['a']) // 1
}
}
</script>
目前已知组件使用emits会导致this不能直接传递给ComponentPublicInstance类型,需要as一下。
function log(ins: ComponentPublicInstance) {
console.log(ins);
}
export default {
emits: ['change', 'input'],
methods: {
buttonClick() {
log(this as ComponentPublicInstance)
}
}
}
如下为进阶说明,可以不看
我们在代码中用到的ComponentPublicInstance为省略泛型的写法,最终推导出的ComponentPublicInstance类型为:
// 此处为方便说明,省略了很多属性、简化了写法
type ComponentPublicInstance = {
$emit: (event: string, ...args: any[]) => void
}
对于使用了emits的组件,最终推导出来的this对应的类型为:
// 此处为方便说明,省略了很多属性、简化了写法
type XxxComponentPublicInstance = {
$emit: (event: 'change' | 'input', ...args: any[]) => void
}
在将XxxComponentPublicInstance类型的this值赋值给ComponentPublicInstance类型的参数时,由于$emit类型无法兼容导致编译报错。
下面我们只看$emit的类型
type ComponentPublicInstanceEmit = (event: string, ...args: any[]) => void
type XxxComponentPublicInstanceEmit = (event: 'change' | 'input', ...args: any[]) => void
对于ComponentPublicInstanceEmit类型的函数A来说,event参数可以接收任意字符串,如果将其赋值为只能接收'change' | 'input'作为event参数的函数B,这时候用户如果将event参数设为'click'则函数B无法处理,而函数A的类型定义又可以接收'click',所以ts并不允许这种行为。
但是反过来则是可以的XxxComponentPublicInstanceEmit类型的函数A可以被重新赋值为ComponentPublicInstanceEmit类型的函数。
总结一下就是ts在比较函数参数是否兼容时使用逆变(contravariance)而非协变(covariance),这两个名词定义比较复杂,结合上述示例理解即可。
this.$xxx
访问,需要使用this.$data['$xxx']
,这是vue的规范。目前安卓端可以使用this.$xxx访问是Bug而非特性,请勿使用此特性。$root
会获取应用根组件,而不是页面根组件。而安卓端是多页应用,$root
获取的是页面根组件。$parent
会获取父组件(含内置组件),安卓端只会获取父级非内置组件,web端后续会调整,请勿利用此特性。deactivate
生命周期,此时部分dom事件无法触发(如:transitionEnd)。可以视情况使用activate
、deactivate
生命周期重新触发dom相关操作。参考:类型兼容性
为保证多端统一,uni-app-x编译到web端时,内置组件根元素带有一些默认样式,详情参考:uvue css使用。如果是使用document.createElement
等方式自行创建的html元素不会有这些默认样式。
通过element.style.xxx设置样式时,web端会自动将样式进行转化,具体取决于浏览器。
例如:
element.style.color = '##FF0000'
element.style.color === 'rgb(255, 0, 0)' // true
position: fixed定位时,web端为相对于整个浏览器页面进行定位,app端为相对于页面(除导航栏、tabbar)定位。可以使用css变量使两端表现一致
.fixed {
position: fixed;
width: 100px;
height: 100px;
background-color: #FF0000;
left: 10px;
/* #ifdef WEB */
top: calc(--window-top + 10px);
/* #endif */
/* #ifdef APP */
top: 10px; /* App端暂不支持calc */
/* #endif */
}
uni相关的异步api在web端不传回调时会返回promise(详情参考:API Promise 化)。但是由于目前缺少此用法的类型定义,使用返回的Promise无法通过编译。另外安卓端暂未实现此功能,建议不要使用此特性。
运行到web端时,uni-app-x编译器不会对语法进行转化来兼容低版本浏览器。发行时会对代码进行转化,以保证低版本浏览器能正常运行。
发行时支持的最低浏览器版本为:chrome 64
、safari 11.1
、firefox 62
、edge 79
、safari on iOS 12
。
UNI-
前缀,例如web端为UNI-VIEW
、UNI-IMAGE
,安卓端为VIEW
、IMAGE
。此问题已在HBuilderX 4.02版本修复,web端移除了UNI-前缀。