tencent cloud

渲染层
最后更新时间:2025-12-08 15:20:57
渲染层
最后更新时间: 2025-12-08 15:20:57
框架的渲染层由 WXML 与 WXSS 编写,由组件来进行展示。将逻辑层的数据反映成视图,同时将渲染层的事件发送给逻辑层。
WXML(WX Markup language) 用于描述页面的结构。
WXS(WX Script) 是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。
WXSS(WX Style Sheet) 用于描述页面的样式。
组件(Component)是视图的基本组成单元。

1. WXML

WXML(WX Markup Language)是框架设计的一套标签语言,结合基础组件事件系统可以构建出页面的结构。
要完整了解 WXML 语法,请参考 WXML 语法参考
用以下一些简单的例子来看看 WXML 具有什么能力:

1.1 数据绑定

<!-- wxml -->
<view> {{message}} </view>
// page.js
Page({
data: {
message: 'Hello MINA!'
}
})

1.2 列表渲染

<!--wxml-->
<view wx:for="{{array}}"> {{item}} </view>

1.3 条件渲染

<!--wxml-->
<view wx:if="{{view == 'WEBVIEW'}}"> WEBVIEW </view>
<view wx:elif="{{view == 'APP'}}"> APP </view>
<view wx:else="{{view == 'MINA'}}"> MINA </view>
// page.js
Page({
data: {
view: 'MINA'
}
})

1.4 模板

<!--wxml-->
<template name="staffName">
<view>
FirstName: {{firstName}}, LastName: {{lastName}}
</view>
</template>

<template is="staffName" data="{{...staffA}}"></template>
<template is="staffName" data="{{...staffB}}"></template>
<template is="staffName" data="{{...staffC}}"></template>
// page.js
Page({
data: {
staffA: {firstName: 'Hulk', lastName: 'Hu'},
staffB: {firstName: 'Shang', lastName: 'You'},
staffC: {firstName: 'Gideon', lastName: 'Lin'}
}
})

2. WXSS

WXSS (WX Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。
WXSS 用来决定 WXML 的组件应该怎么显示。
为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发小程序,WXSS 对 CSS 进行了扩充以及修改。
与 CSS 相比,WXSS 扩展的特性有:
尺寸单位
样式导入
注意:
iOS 8 及以下的 iOS 版本,如使用 flexbox 布局,需添加display: -webkit-flex属性。

2.1 尺寸单位

rpx(responsive pixel):可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
根据不同的设备屏幕宽度,rpx 和 px 的换算关系也会有所不同。例如:
设备
屏幕宽度
rpx 换算 px(屏幕宽度/750)
px 换算 rpx (750/屏幕宽度)
iPhone5
320px
1rpx = 0.42px
1px = 2.34rpx
iPhone6
375px
1rpx = 0.5px
1px = 2rpx
iPhone6 Plus
414px
1rpx = 0.552px
1px = 1.81rpx
说明:
建议: 开发小程序时设计师可以用 iPhone6 作为视觉稿的标准。
注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况。

2.2 样式导入

使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用;表示语句结束。
示例代码:
/** common.wxss **/
.small-p {
padding:5px;
}
/** app.wxss **/
@import "common.wxss";
.middle-p {
padding:15px;
}

2.3 内联样式

框架组件上支持使用 style、class 属性来控制组件的样式。
style:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。
/** common.wxss **/
.small-p {
padding:5px;
}
class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上,样式类名之间用空格分隔。
<view class="normal_view" />

2.4 选择器

目前支持的选择器有:
选择器
样例
样例描述
.class
.intro
选择所有拥有 class="intro" 的组件
#id
#firstname
选择拥有 id="firstname" 的组件
element
view
选择所有 view 组件
element,element
view, checkbox
选择所有文档的 view 组件和所有的 checkbox 组件
::after
view::after
在 view 组件后边插入内容
::before
view::before
在 view 组件前边插入内容

2.5 全局样式与局部样式

定义在 app.wxss 中的样式为全局样式,作用于每一个页面。在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。

3. WXS

WXS(WX Script)是内联在 WXML 中的脚本段。通过 WXS 可以在模板中内联少量处理脚本,丰富模板的数据预处理能力。另外,WXS 还可以用来编写简单的 WXS 事件响应函数
从语法上看,WXS 类似于有少量限制的 JavaScript 。要完整了解 WXS 语法,请参考WXS - 介绍
以下是一些使用 WXS 的简单示例。 页面渲染:
<!--wxml-->
<wxs module="m1">
var msg = "hello world";

module.exports.message = msg;
</wxs>

<view> {{m1.message}} </view>
页面输出:
hello world
数据处理:
// page.js
Page({
data: {
array: [1, 2, 3, 4, 5, 1, 2, 3, 4]
}
})
<!--wxml-->
<!-- 下面的 getMax 函数,接受一个数组,且返回数组中最大的元素的值 -->
<wxs module="m1">
var getMax = function(array) {
var max = undefined;
for (var i = 0; i < array.length; ++i) {
max = max === undefined ?
array[i] :
(max >= array[i] ? max : array[i]);
}
return max;
}

module.exports.getMax = getMax;
</wxs>

<!-- 调用 wxs 里面的 getMax 函数,参数为 page.js 里面的 array -->
<view> {{m1.getMax(array)}} </view>
页面输出:
5

4. 事件系统

4.1 什么是事件

事件是渲染层到逻辑层的通讯方式。
事件可以将用户的行为反馈到逻辑层进行处理。
事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
事件对象可以携带额外信息,如 id, dataset, touches。

4.2 事件的使用方式

在组件中绑定一个事件处理函数。
bindtap,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数。
<view id="tapTest" data-hi="Weixin" bindtap="tapName"> Click me! </view>
在相应的Page定义中写上相应的事件处理函数,参数是event
Page({
tapName: function(event) {
console.log(event)
}
})
可以看到log出来的信息大致如下:
{
"type":"tap",
"timeStamp":895,
"target": {
"id": "tapTest",
"dataset": {
"hi":"Weixin"
}
},
"currentTarget": {
"id": "tapTest",
"dataset": {
"hi":"Weixin"
}
},
"detail": {
"x":53,
"y":14
},
"touches":[{
"identifier":0,
"pageX":53,
"pageY":14,
"clientX":53,
"clientY":14
}],
"changedTouches":[{
"identifier":0,
"pageX":53,
"pageY":14,
"clientX":53,
"clientY":14
}]
}

4.3 使用WXS函数响应事件

4.3.1 背景

有频繁用户交互的效果在小程序上表现是比较卡顿的,例如页面有2个元素 A 和 B,用户在 A 上做 touchmove 手势,要求 B 也跟随移动,movable-view 就是一个典型的例子。一次 touchmove 事件的响应过程为:
touchmove 事件从渲染层(Webview)抛到逻辑层(App Service);
逻辑层(App Service)处理 touchmove 事件,再通过 setData 来改变 B 的位置。
一次 touchmove 的响应需要经过 2 次的逻辑层和渲染层的通信以及一次渲染,通信的耗时比较大。此外 setData 渲染也会阻塞其它脚本执行,导致了整个用户交互的动画过程会有延迟。

4.3.2 解决方案

本方案基本的思路是减少通信的次数,让事件在渲染层(Webview)响应。小程序的框架分为渲染层(Webview)和逻辑层(App Service),这样分层的目的是管控,开发者的代码只能运行在逻辑层(App Service),而这个思路就必须要让开发者的代码运行在渲染层(Webview)。
使用 WXS 函数用来响应小程序事件,目前只能响应内置组件的事件,不支持自定义组件事件。
WXS 函数的除了纯逻辑的运算,还可以通过封装好的 ComponentDescriptor 实例来访问以及设置组件的 class 和样式,对于交互动画,设置 style 和 class 足够了。
WXS 函数接受2个参数,第一个是 event,在原有的 event 的基础上加了event.instance对象,第二个参数是ownerInstanceevent.instance一样是一个ComponentDescriptor对象。具体使用如下:
在组件中绑定和注册事件处理的 WXS 函数:
<wxs module="wxs" src="./test.wxs"></wxs>
<view id="tapTest" data-hi="Weixin" bindtap="{{wxs.tapName}}"> Click me! </view>
**注:绑定的WXS函数必须用{{}}括起来**
test.wxs 文件实现 tapName 函数:
function tapName(event, ownerInstance) {
console.log('tap Weixin', JSON.stringify(event))
}
module.exports = {
tapName: tapName
}
ownerInstance 包含了一些方法,可以设置组件的样式和 class。
WXS 函数的例子如下:
var wxsFunction = function(event, ownerInstance) {
var instance = ownerInstance.selectComponent('.classSelector') // 返回组件的实例
instance.setStyle({
"font-size": "14px" // 支持rpx
})
instance.getDataset()
instance.setClass(className)
// ...
return false // 不往上冒泡,相当于调用了同时调用了stopPropagation和preventDefault
}
其中入参 event 是小程序事件对象基础上多了 event.instance 来表示触发事件的组件的 ComponentDescriptor 实例。
ownerInstance 表示的是触发事件的组件所在的组件的 ComponentDescriptor 实例,如果触发事件的组件是在页面内的,则 ownerInstance 表示的是页面实例。
ComponentDescriptor 目前支持的 API 如下:
方法
参数
描述
selectComponent
selector 对象
返回组件的 ComponentDescriptor 实例。
selectAllComponents
selector对象数组
返回组件的 ComponentDescriptor 实例数组。
setStyle
Object/string
设置组件样式,支持rpx。设置的样式优先级比组件 wxml 里面定义的样式高。不能设置最顶层页面的样式。
addClass/removeClass/hasClass
string
设置组件的 class。设置的 class 优先级比组件 wxml 里面定义的 class 高。不能设置最顶层页面的 class。
getDataset
返回当前组件/页面的 dataset 对象。
callMethod
(funcName:string, args:object)
调用当前组件/页面在逻辑层(App Service)定义的函数。funcName 表示函数名称,args 表示函数的参数。
getState
返回一个 object 对象,当有局部变量需要存储起来后续使用的时候用这个方法。
triggerEvent
(eventName, detail)
和组件的triggerEvent一致。

4.3.3 使用方法

WXML 定义事件:
<wxs module="test" src="./test.wxs"></wxs>
<view
change:prop="{{test.propObserver}}"
prop="{{propValue}}"
bindtouchmove="{{test.touchmove}}"
class="movable">
</view>
上面的 change:prop(属性前面带 change: 前缀)是在 prop 属性被设置的时候触发 WXS 函数,值必须用{{}} 括起来。类似 Component 定义的 properties 里面的 observer 属性,在 setData({propValue: newValue}) 调用之后会触发。
注意:
WXS 函数必须用 {{}} 括起来。当 prop 的值被设置 WXS 函数就会触发,而不只是值发生改变,所以在页面初始化的时候会调用一次 WxsPropObserver 的函数。
WXS 文件 test.wxs 里面定义并导出事件处理函数和属性改变触发的函数:
module.exports = {
touchmove: function(event, instance) {
console.log('log event', JSON.stringify(event))
},
propObserver: function(newValue, oldValue, ownerInstance, instance) {
console.log('prop observer', newValue, oldValue)
}
}

4.4 事件详解

4.4.1 事件分类

事件分为冒泡事件和非冒泡事件:
冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递;
非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。
WXML的冒泡事件列表:
类型
触发条件
touchstart
手指触摸动作开始
touchmove
手指触摸后移动
touchcancel
手指触摸动作被打断,如来电提醒,弹窗
touchend
手指触摸动作结束
tap
手指触摸后马上离开
longpress
手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap 事件将不被触发
longtap
手指触摸后,超过350ms再离开(推荐使用 longpress 事件代替)
transitionend
会在 WXSS transition 或 wx.createAnimation 动画结束后触发
animationstart
会在一个 WXSS animation 动画开始时触发
animationiteration
会在一个 WXSS animation 一次迭代结束时触发
animationend
会在一个 WXSS animation 动画完成时触发
touchforcechange
在支持 3D Touch 的 iPhone 设备,重按时会触发
说明:
除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如 form 的submit事件,input 的input事件,scroll-view 的scroll事件,(详见 组件概览)

4.4.2 普通事件绑定

事件绑定的写法类似于组件的属性,如:
<view bindtap="handleTap">
Click here!
</view>
如果用户点击这个 view ,则页面的 handleTap 会被调用。
事件绑定函数可以是一个数据绑定,如:
<view bindtap="{{ handlerName }}">
Click here!
</view>
此时,页面的 this.data.handlerName 必须是一个字符串,指定事件处理函数名;如果它是个空字符串,则这个绑定会失效(可以利用这个特性来暂时禁用一些事件)。
在大多数组件和自定义组件中, bind 后可以紧跟一个冒号,其含义不变,如 bind:tap

4.4.3 绑定并阻止事件冒泡

bind外,也可以用catch来绑定事件。与bind不同,catch会阻止事件向上冒泡。
例如在下边这个例子中,单击 inner view 会先后调用handleTap3handleTap2(因为 tap 事件会冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父节点传递),单击 middle view 会触发handleTap2,单击 outer view 会触发handleTap1
<view id="outer" bindtap="handleTap1">
outer view
<view id="middle" catchtap="handleTap2">
middle view
<view id="inner" bindtap="handleTap3">
inner view
</view>
</view>
</view>

4.4.4 互斥事件绑定

自基础库版本 1.5.44 起,除 bindcatch 外,还可以使用 mut-bind 来绑定事件。一个 mut-bind 触发后,如果事件冒泡到其他节点上,其他节点上的 mut-bind绑定函数不会被触发,但 bind 绑定函数和 catch 绑定函数依旧会被触发。
换而言之,所有 mut-bind 是“互斥”的,只会有其中一个绑定函数被触发。同时,它完全不影响 bindcatch 的绑定效果。
例如在下边这个例子中,单击 inner view 会先后调用 handleTap3handleTap2 ,单击 middle view 会调用 handleTap2handleTap1
<view id="outer" mut-bind:tap="handleTap1">
outer view
<view id="middle" bindtap="handleTap2">
middle view
<view id="inner" mut-bind:tap="handleTap3">
inner view
</view>
</view>
</view>

4.4.5 事件的捕获阶段

触摸类事件支持捕获阶段。捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段恰好相反。需要在捕获阶段监听事件时,可以采用capture-bindcapture-catch关键字,后者将中断捕获阶段和取消冒泡阶段。
在下面的代码中,单击 inner view 会先后调用handleTap2handleTap4handleTap3handleTap1
<view id="outer" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2">
outer view
<view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
inner view
</view>
</view>
如果将上面代码中的第一个 capture-bind 改为 capture-catch,将只触发 handleTap2。
<view id="outer" bind:touchstart="handleTap1" capture-catch:touchstart="handleTap2">
outer view
<view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
inner view
</view>
</view>

4.4.6 事件对象

如无特殊说明,当组件触发事件时,逻辑层绑定该事件的处理函数会收到一个事件对象。
BaseEvent 基础事件对象属性列表:
属性
类型
说明
type
String
事件类型
timeStamp
Integer
事件生成时的时间戳
target
Object
触发事件的组件的一些属性值集合
currentTarget
Object
当前组件的一些属性值集合
CustomEvent 自定义事件对象属性列表(继承 BaseEvent):
属性
类型
说明
detail
Object
额外的信息
TouchEvent 触摸事件对象属性列表(继承 BaseEvent):
属性
类型
说明
touches
Array
触摸事件,当前停留在屏幕中的触摸点信息的数组
changedTouches
Array
触摸事件,当前变化的触摸点信息的数组
特殊事件:canvas 中的触摸事件不可冒泡,所以没有 currentTarget。

4.4.7 type

代表事件的类型。

4.4.8 timeStamp

页面打开到触发事件所经过的毫秒数。

4.4.9 target

触发事件的源组件。
属性
类型
说明
id
String
事件源组件的 id
dataset
Object
事件源组件上由 data - 开头的自定义属性组成的集合

4.4.10 currentTarget

事件绑定的当前组件。
属性
类型
说明
id
String
当前组件的 id
dataset
Object
当前组件上由 data - 开头的自定义属性组成的集合
说明:
target 和 currentTarget 可以参考上例中,单击 inner view 时,handleTap3 收到的事件对象 target 和 currentTarget 都是 inner,而 handleTap2 收到的事件对象 target 就是 inner,currentTarget 就是 middle。

4.4.11 dataset

在组件节点中可以附加一些自定义数据。这样,在事件中可以获取这些自定义的节点数据,用于事件的逻辑处理。
在 WXML 中,这些自定义数据以 data- 开头,多个单词由连字符 - 连接。这种写法中,连字符写法会转换成驼峰写法,而大写字符会自动转成小写字符。如:
data-element-type ,最终会呈现为 event.currentTarget.dataset.elementType ;
data-elementType ,最终会呈现为 event.currentTarget.dataset.elementtype 。
代码示例:
<view data-alpha-beta="1" data-alphaBeta="2" bindtap="bindViewTap"> DataSet Test </view>

Page({
bindViewTap:function(event){
event.currentTarget.dataset.alphaBeta === 1 // - 会转为驼峰写法
event.currentTarget.dataset.alphabeta === 2 // 大写会转为小写
}
})

4.4.12 touches

touches 是一个数组,每个元素为一个 Touch 对象(canvas 触摸事件中携带的 touches 是 CanvasTouch 数组)。表示当前停留在屏幕上的触摸点。
Touch 对象
属性
类型
说明
identifier
Number
触摸点的标识符
pageX, pageY
Number
距离文档左上角的距离,文档的左上角为原点,横向为X轴,纵向为Y轴
clientX, clientY
Number
距离页面可显示区域(屏幕除去导航条)左上角距离,横向为X轴,纵向为Y轴
CanvasTouch对象
属性
类型
说明
identifier
Number
触摸点的标识符
x, y
Number
距离 Canvas 左上角的距离,Canvas 的左上角为原点 ,横向为X轴,纵向为Y轴

4.4.13 changedTouches

changedTouches 数据格式同 touches。 表示有变化的触摸点,如从无变有(touchstart),位置变化(touchmove),从有变无(touchend、touchcancel)。

4.4.14 detail

自定义事件所携带的数据,如表单组件的提交事件会携带用户的输入,媒体的错误事件会携带错误信息,详见 组件概览 定义中各个事件的定义。
单击事件的detail 带有的 x, y 同 pageX, pageY 代表距离文档左上角的距离。

5. 基础组件

框架为开发者提供了一系列基础组件,开发者可以通过组合这些基础组件进行快速开发。详细介绍请参考 组件概览
什么是组件:
组件是视图层的基本组成单元。
一个组件通常包括开始标签结束标签属性用来修饰这个组件,内容在两个标签之内。
<tagname property="value">
Content goes here ...
</tagname>
注意:
所有组件与属性都是小写,以连字符-连接。
属性类型:
类型
描述
注解
Boolean
布尔值
组件写上该属性,不管是什么值都被当作 true;只有组件上没有该属性时,属性值才为false。 如果属性值为变量,变量的值会被转换为 Boolean 类型。
Number
数字
1, 2.5
String
字符串
"string"
Array
数组
[ 1, "string" ]
Object
对象
{ key: value }
EventHandler
事件处理函数名
"handlerName" 是 Page 中定义的事件处理函数名
Any
任意属性
-
公共属性
所有组件都有以下属性:
属性名
类型
描述
注解
id
String
组件的唯一标示
保持整个页面唯一
class
String
组件的样式类
在对应的 WXSS 中定义的样式类
style
String
组件的内联样式
可以动态设置的内联样式
hidden
Boolean
组件是否显示
所有组件默认显示
data-*
Any
自定义属性
组件上触发的事件时,会发送给事件处理函数
bind* / catch*
EventHandler
组件的事件
详见事件
特殊属性
几乎所有组件都有各自定义的属性,可以对该组件的功能或样式进行修饰,请参考各个 组件概览 的定义。

6. 获取界面上的节点信息

6.1 WXML节点信息

节点信息查询 API 可以用于获取节点属性、样式、在界面上的位置等信息。
最常见的用法是使用这个接口来查询某个节点的当前位置,以及界面的滚动位置。
示例代码:
const query = wx.createSelectorQuery()
query.select('#the-id').boundingClientRect(function(res){
res.top // #the-id 节点的上边界坐标(相对于显示区域)
})
query.selectViewport().scrollOffset(function(res){
res.scrollTop // 显示区域的竖直滚动位置
})
query.exec()
上述示例中, #the-id 是一个节点选择器,与 CSS 的选择器相近但略有区别,请参见 SelectorQuery.select 的相关说明。
在自定义组件或包含自定义组件的页面中,推荐使用 this.createSelectorQuery 来代替 wx.createSelectorQuery,这样可以确保在正确的范围内选择节点。

6.2 WXML节点布局相交状态

节点布局相交状态 API 可用于监听两个或多个组件节点在布局位置上的相交状态。这一组 API 常常可以用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见。
这一组 API 涉及的主要概念如下。
参照节点:监听的参照节点,取它的布局区域作为参照区域。如果有多个参照节点,则会取它们布局区域的 交集 作为参照区域。页面显示区域也可作为参照区域之一;
目标节点:监听的目标,默认只能是一个节点(使用 selectAll 选项时,可以同时监听多个节点);
相交区域:目标节点的布局区域与参照区域的相交区域;
相交比例:相交区域占参照区域的比例;
阈值:相交比例如果达到阈值,则会触发监听器的回调函数。阈值可以有多个;
以下示例代码可以在目标节点(用选择器 .target-class指定)每次进入或离开页面显示区域时,触发回调函数。
示例代码:
Page({
onLoad: function(){
wx.createIntersectionObserver().relativeToViewport().observe('.target-class', (res) => {
res.id // 目标节点 id
res.dataset // 目标节点 dataset
res.intersectionRatio // 相交区域占目标节点的布局区域的比例
res.intersectionRect // 相交区域
res.intersectionRect.left // 相交区域的左边界坐标
res.intersectionRect.top // 相交区域的上边界坐标
res.intersectionRect.width // 相交区域的宽度
res.intersectionRect.height // 相交区域的高度
})
}
})
以下示例代码可以在目标节点(用选择器 .target-class 指定)与参照节点(用选择器 .relative-class 指定)在页面显示区域内相交或相离,且相交或相离程度达到目标节点布局区域的20%和50%时,触发回调函数。
示例代码:
Page({
onLoad: function(){
wx.createIntersectionObserver(this, {
thresholds: [0.2, 0.5]
}).relativeTo('.relative-class').relativeToViewport().observe('.target-class', (res) => {
res.intersectionRatio // 相交区域占目标节点的布局区域的比例
res.intersectionRect // 相交区域
res.intersectionRect.left // 相交区域的左边界坐标
res.intersectionRect.top // 相交区域的上边界坐标
res.intersectionRect.width // 相交区域的宽度
res.intersectionRect.height // 相交区域的高度
})
}
})
注意:
与页面显示区域的相交区域并不准确代表用户可见的区域,因为参与计算的区域是“布局区域”,布局区域可能会在绘制时被其他节点裁剪隐藏(如遇祖先节点中 overflow 样式为 hidden 的节点)或遮盖(如遇 fixed 定位的节点)。
在自定义组件或包含自定义组件的页面中,推荐使用 this.createIntersectionObserver 来代替 wx.createIntersectionObserver ,这样可以确保在正确的范围内选择节点。

7. 响应显示区域变化

7.1 显示区域尺寸

显示区域指小程序界面中可以自由布局展示的区域。在默认情况下,小程序显示区域的尺寸自页面初始化起就不会发生变化。但以下三种方式都可以改变这一默认行为。
在手机上启用屏幕旋转支持
小程序在手机上支持屏幕旋转。使小程序中的页面支持屏幕旋转的方法是:在 app.jsonwindow 段中设置 "pageOrientation": "auto" ,或在页面 json 文件中配置 "pageOrientation": "auto"
以下是在单个页面 json 文件中启用屏幕旋转的示例。
代码示例:
{
"pageOrientation": "auto"
}
如果页面添加了上述声明,则在屏幕旋转时,这个页面将随之旋转,显示区域尺寸也会随着屏幕旋转而变化。pageOrientation 还可以被设置为 landscape ,表示固定为横屏显示。
在iPad上启用屏幕旋转支持
在 iPad 上运行的小程序可以支持屏幕旋转。使小程序支持 iPad 屏幕旋转的方法是:在 app.json 中添加 "resizable": true 。
代码示例:
{
"resizable": true
}
如果小程序添加了上述声明,则在屏幕旋转时,小程序将随之旋转,显示区域尺寸也会随着屏幕旋转而变化。
注意:
在 iPad 上不能单独配置某个页面是否支持屏幕旋转。

7.2 Media Query

有时,对于不同尺寸的显示区域,页面的布局会有所差异。此时可以使用 media query 来解决大多数问题。
代码示例:
.my-class {
width: 40px;
}

@media (min-width: 480px) {
/* 仅在 480px 或更宽的屏幕上生效的样式规则 */
.my-class {
width: 200px;
}
}

7.3 屏幕旋转事件

有时,仅仅使用 media query 无法控制一些精细的布局变化。此时可以使用 js 作为辅助。
在 js 中读取页面的显示区域尺寸,可以使用 selectorQuery.selectViewport
页面尺寸发生改变的事件,可以使用页面的 onResize 来监听。对于自定义组件,可以使用 resize 生命周期来监听。回调函数中将返回显示区域的尺寸信息。
代码示例:
Page({
onResize(res) {
res.size.windowWidth // 新的显示区域宽度
res.size.windowHeight // 新的显示区域高度
}
})
Component({
pageLifetimes: {
resize(res) {
res.size.windowWidth // 新的显示区域宽度
res.size.windowHeight // 新的显示区域高度
}
}
})
此外,还可以使用 wx.onWindowResize 来监听(但这不是推荐的方式)。

8. 页面动画

8.1 界面动画的常见方式

在小程序中,通常可以使用 CSS 渐变 和 CSS 动画 来创建简易的界面动画。
动画过程中,可以使用 bindtransitionend bindanimationstart bindanimationiteration bindanimationend 来监听动画事件。
事件名
含义
transitionend
CSS 渐变结束或 wx.createAnimation 结束一个阶段
animationstart
CSS 动画开始
animationiteration
CSS 动画结束一个阶段
animationend
CSS 动画结束
说明:
这几个事件都不是冒泡事件,需要绑定在真正发生了动画的节点上才会生效。
同时,还可以使用 wx.createAnimation 接口来动态创建简易的动画效果(新版小程序基础库中推荐使用下述的关键帧动画接口代替)。

8.2 高级的动画方式

在一些复杂场景下,上述的动画方法可能并不适用。
WXS 响应事件 的方式可以通过使用 WXS 来响应事件的方法来动态调整节点的 style 属性。通过不断改变 style 属性的值可以做到动画效果。同时,这种方式也可以根据用户的触摸事件来动态地生成动画。
连续使用 setData 来改变界面的方法也可以达到动画的效果。这样可以任意地改变界面,但通常会产生较大的延迟或卡顿,甚至导致小程序僵死。此时可以通过将页面的 setData 改为 自定义组件 中的 setData 来提升性能。

本页内容是否解决了您的问题?
您也可以 联系销售 提交工单 以寻求帮助。

文档反馈