概述
小程序框架的视图层由 WXML 和 WXSS 编写,由组件来进行展示。WXML 用于描述页面的结构,而 WXSS 用于描述页面的样式。WXS 是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。
框架的逻辑层负责将数据转化为视图,同时将视图层的事件发送给逻辑层。这样,开发者可以专注于数据和逻辑的处理,而不必过多关注视图层的实现细节。
组件是视图的基本组成单元,可以帮助开发者更轻松地实现各种功能和交互效果。开发者可以自定义组件,也可以使用框架提供的组件库,从而快速地构建出具有原生 App 体验的服务。
WXML
WXSS
基础组件
说明
框架为开发者提供了一系列基础组件,开发者可以通过组合这些基础组件进行快速开发。
什么是组件:
组件是视图层的基本组成单元。
组件自带一些功能与 TMF 风格一致的样式。
一个组件通常包括
开始标签
和结束标签
,属性
用来修饰这个组件,内容
在两个标签之内。<tagname property="value">Content goes here ...</tagname>
说明:
所有组件与属性都是小写,以连字符-连接。
属性类型
类型 | 描述 | 注解 |
Boolean | 布尔值 | 组件写上该属性,不管是什么值都被当作 True;只有组件上没有该属性时,属性值才为 False。如果属性值为变量,变量的值会被转换为 Boolean 类型 |
Number | 数字 | 1, 2.5 |
String | 字符串 | "string" |
Array | 数组 | [ 1, "string" ] |
Object | 对象 | { key: value } |
EventHandler | 事件处理函数名 | |
Any | 任意属性 | - |
公共属性
所有组件都有以下属性:
属性名 | 类型 | 描述 | 注解 |
id | string | 组件的唯一标识 | 保持整个页面唯一 |
class | string | 组件的唯一标识 | 在对应的 WXSS 中定义的样式类 |
style | string | 组件的内联样式 | 可以动态设置的内联样式 |
hidden | boolean | 组件是否显示 | 所有组件默认显示 |
date-* | any | 自定义属性 | 组件上触发的事件时,会发送给事件处理函数 |
bind/catch | eventhandler | 组件的事件 |
特殊属性
获取界面上的节点信息
WXML 节点信息
最常见的用法是使用这个接口来查询某个节点的当前位置,以及界面的滚动位置。
示例代码:
const query = wx.createSelectorQuery()query.select('#the-id').boundingClientRect(function (res) {res.top // #the-id 节点的上边界坐标(相对于显示区域)})query.selectViewport().scrollOffset(function (res) {res.scrollTop // 显示区域的竖直滚动位置})query.exec()
WXML 节点布局相交状态
这一组 API 涉及的主要概念如下。
参照节点:监听的参照节点,取它的布局区域作为参照区域。如果有多个参照节点,则会取它们布局区域的交集作为参照区域。页面显示区域也可作为参照区域之一。
目标节点:监听的目标,默认只能是一个节点(使用
selectAll
选项时,可以同时监听多个节点)。相交区域:目标节点的布局区域与参照区域的相交区域。
相交比例:相交区域占参照区域的比例。
阈值:相交比例如果达到阈值,则会触发监听器的回调函数。阈值可以有多个。
以下示例代码可以在目标节点(用选择器
.target-class
指定)每次进入或离开页面显示区域时,触发回调函数。示例代码:
Page({onLoad() {wx.createIntersectionObserver().relativeToViewport().observe('.target-class', (res) => {res.id // 目标节点 idres.dataset // 目标节点 datasetres.intersectionRatio // 相交区域占目标节点的布局区域的比例res.intersectionRect // 相交区域res.intersectionRect.left // 相交区域的左边界坐标res.intersectionRect.top // 相交区域的上边界坐标res.intersectionRect.width // 相交区域的宽度res.intersectionRect.height // 相交区域的高度})}})
以下示例代码可以在目标节点(用选择器 .target-class 指定)与参照节点(用选择器 .relative-class 指定)在页面显示区域内相交或相离,且相交或相离程度达到目标节点布局区域的20%和50%时,触发回调函数。
示例代码:
Page({onLoad() {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,这样可以确保在正确的范围内选择节点。响应显示区域变化
显示区域尺寸
显示区域指小程序界面中可以自由布局展示的区域。在默认情况下,小程序显示区域的尺寸自页面初始化起就不会发生变化。但以下两种方式都可以改变这一默认行为。
在手机上启用屏幕旋转支持
小程序在手机上支持屏幕旋转。使小程序中的页面支持屏幕旋转的方法是:在
app.json
的 window
段中设置 "pageOrientation": "auto"
,或在页面 json 文件中配置 "pageOrientation": "auto"
。以下是在单个页面 json 文件中启用屏幕旋转的示例。
代码示例:
{"pageOrientation": "auto"}
在iPad上启用屏幕选择支持
在 iPad 上运行的小程序可以支持屏幕旋转。使小程序支持 iPad 屏幕旋转的方法是:在
app.json
中添加 "resizable": true
。代码示例:
{"resizable": true}
Media Query
有时,对于不同尺寸的显示区域,页面的布局会有所差异。此时可以使用 media query 来解决大多数问题。
代码示例:
.my-class {width: 40px;}@media (min-width: 480px) {/* 仅在 480px 或更宽的屏幕上生效的样式规则 */.my-class {width: 200px;}}
屏幕旋转事件
有时,仅仅使用 media query 无法控制一些精细的布局变化。此时可以使用 js 作为辅助。
页面尺寸发生改变的事件,可以使用页面的
onResize
来监听。对于自定义组件,可以使用 resize 生命周期来监听。回调函数中将返回显示区域的尺寸信息。代码示例:
Page({onResize(res) {res.size.windowWidth // 新的显示区域宽度res.size.windowHeight // 新的显示区域高度}})
Component({pageLifetimes: {resize(res) {res.size.windowWidth // 新的显示区域宽度res.size.windowHeight // 新的显示区域高度}}})
此外,还可以使用
wx.onWindowResize
来监听(但这不是推荐的方式)。动画
界面动画的常见方式
动画过程中,可以使用
bindtransitionend
bindanimationstart
bindanimationiteration
bindanimationend
来监听动画事件。transitionend:CSS 渐变结束或 wx.createAnimation 结束一个阶段。
animationstart:CSS 动画开始。
animationiteration:CSS 动画结束一个阶段。
animationend:CSS 动画结束。
说明:
这几个事件都不是冒泡事件,需要绑定在真正发生了动画的节点上才会生效。
高级的动画方式
在一些复杂场景下,上述的动画方法可能并不适用。
WXML 相应事件 的方式可以通过使用 QS 来响应事件的方法来动态调整节点的 style 属性。通过不断改变 style 属性的值可以做到动画效果。同时,这种方式也可以根据用户的触摸事件来动态地生成动画。
使用连续使用 setData 来改变界面的方法也可以达到动画的效果。这样可以任意地改变界面,但通常会产生较大的延迟或卡顿,甚至导致小程序僵死。此时可以通过将页面的 setData 改为 自定义模块组件 中的 setData 来提升性能。