# 编译到小程序端

新增于 HBuilderX 4.41+

uni-app x 项目在编译到小程序平台时,将部分特性对齐了web与app端,因此和非uni-app x项目编译到小程序端略有差异。

# 基础库范围

截止到4.41发版时微信的主流基础库版本是3.7.1。uni-app x主要是在这个版本库上适配。已知过老的基础库版本上,scroll-view区域大小会不准确。请开发者检查并确保基础库版本大于3.7.1。

# uts

推荐使用uts跨端开发,但微信小程序上也支持js/ts。

# vue

# 自定义组件启用virtualHost带来的影响

标准的小程序下的自定义组件会多套一层DOM,这会影响flex等样式。而uni-app x默认都是flex的。

所以为了拉齐样式表现,uni-app x 项目在编译到小程序时,默认启用了virtualHost,该配置是小程序平台提供的一种策略,可以取消多套的一层。\n 同时默认启用了mergeVirtualHostAttributes特性,在取消多套的一层后,将原本父层的属性设置,合并到子层。

去掉一层以及合并父属性到子,这2件事会对真实渲染的DOM产生影响。尤其会影响在组件外获取组件的DOM

我们先看一个例子:

有个组件c1,父级外层代码如下

<c1 id="c1parent" ref="c1ref" class="class1parent"></c1>

c1组件的代码如下:

<template>
    <view class="classchild">
    </view>
</template>

然后看下mergeVirtualHostAttributes属性合并策略(HBuilderX 4.42+):

  1. 仅将组件外层设置的 id、style、class 以及 v-show 指令生成的 hidden 属性,这4个属性合并到 vue 组件编译成的小程序组件根节点上,其他外层设置的属性都丢弃了。
  2. 仅对组件是单个根节点才会合并,组件内多个根节点的时候不会合并。父层全部丢弃。

根据策略看,上述代码在运行时合并后,父层的id、class属性合并到组件根节点上,所以class1parentclasschild 同时生效。

父层通过uni.createSelectorQuery().in(this.$page).select('#c1parent')拿不到NodesRef。

但createSelectorQuery是支持设定查找范围的,上面的代码是在页面里查找,如果在父层代码里通过in方法指定查找组件,例如:uni.createSelectorQuery().in(this.$refs['c1ref'] as ComponentPublicInstance).select('#c1parent') ,可以拿到c1组件的NodesRef

父层通过uni.getElementById("c1parent")也可以拿到UniElement。

实际上,不管是通过.class1parent 还是 .classchild,都可以拿到。因为样式合并后,这2个class在运行时同时存在。

vue组件的方法调用不受影响,ref取到组件后,可以直接调用组件的方法。

# refs

非 uni-app x 项目使用refs取内置组件引用时会获取到undefined,而 uni-app x 项目会获取到对应的UniElement。

# dom

# UniElement

小程序端逻辑层与是图层分离,导致大多数同步的dom api都不可用。

UniElement在小程序端仅支持如下属性/方法:

  • id 元素的id属性
  • nodeName 元素的节点名
  • tagName 元素的标签名
  • style 元素的style对象,可以通过style对象调用style.setProperty方法
  • getBoundingClientRectAsync 异步获取元素的布局位置信息
  • getAttribute 获取元素的属性值,目前仅支持id、style

注意

  • 小程序端只有UniElement,不支持UniButtonElement、UniViewElement等类
  • 小程序端在各种事件在target、currentTarget指向未配置id的组件时,event.target、event.currentTarget会返回一个功能缺失的UniElement,仅能访问dataset、offsetTop、offsetLeft属性。
  • 小程序端在各种事件在target、currentTarget指向配置了id的组件时,event.target、event.currentTarget会返回一个功能和getElementById一致的UniElement,除了能访问getElementById返回的UniElement的各种属性方法之外,还能访问dataset、offsetTop、offsetLeft属性。

# 事件

click、tap事件上补充了如下属性,使其表现更像PointerEvent:

event.x
event.y
event.clientX
event.clientY
event.pageX
event.pageY
event.screenX
event.screenY

# css

# 样式重置

App平台的ucss和webview的标准css略有差异。为保证多端统一,uni-app-x编译到小程序端时,会进行浏览器样式重置,内置组件根元素带有一些默认样式,详情参考:uvue css使用

如果你不开发App,且不需要样式重置,想使用原始的小程序样式,那么可以在pages.json的globalStyle或对应的页面style内配置enableUcssReset为false来关闭ucss样式重置。参考:page.json文档

# skyline

对skyline的支持处于实验阶段。

目前编译器会根据页面是否为skyline来决定是否注入ucss样式覆盖,仅webview渲染的页面才会进行ucss样式覆盖。

worklet函数暂不支持写在uvue、uts文件内,推荐从js文件内引用。

# 其他差异

# 文件命名

页面或组件目录下,不能使用与 uvue 同名的 uts 文件。
小程序端 uvue 文件会被编译为同名的 js、json、wxml、wxss 文件,如果存在同名 uts 文件,会导致冲突。

# 实体字符

uni-app x项目在编译到小程序端时,如果页面内静态的使用了实体字符&gt;、&lt;、&thinsp;、&nbsp;、&ensp;、&emsp;则会在最终输出的小程序页面文件中保留这些实体字符,例如&nbsp;在微信小程序的wxml文件中仍为&nbsp;不会被转为空格, 而非uni-app-x项目&nbsp;会转为空格。

# radio、checkbox组件使用justify-content等属性对齐插槽内容与选择框时与app、web表现不一致

此表现后续可能会调整,请勿依赖此特性进行布局

由于小程序端radio、checkbox组件内部有一层额外节点,如下属性设置在根节点上不能按预期方式布局插槽内容与选择框

flex-direction
align-content
justify-content
align-items

# 开发和调试

在HBuilderX底部状态栏选择语法平台,确保有微信小程序平台,否则代码提示不会有微信专有API。如果选择其他平台,但代码里在非MP-WEIXIN的条件编译里写了微信专有代码,ide会告警。