wxml 模板语法
1.1 数据绑定的 基本原则
- 在 data 中定义数据
- 在 WXML 中使用数据
1.2 在data中定义页面的数据
像这样:
Page({
data: {
// 字符串类型的数据
info:'init data',
// 数组类型的数据
msgList: [{msg: 'hello'}, {msg: 'world'}]
}
})1.3 Mustache 语法的格式
把data 中的数据绑定到页面中渲染,使用 Mustache 语法 (双大括号)将变量包起来即可。
1.4 Mustache 语法的应用场景
- 绑定内容
- 绑定属性
- 运算(包括三元运算、算数运算符)
1.4.1 动态绑定内容
页面的数据如下:
Page({
data: {
// 字符串类型的数据
info:'init data',
// 数组类型的数据
msgList: [{msg: 'hello'}, {msg: 'world'}]
}
})结构为:
<image src="{{ imgSrc }}"></image>1.4.2 三元运算
页面的数据如下:
Page({
data: {
randomNum: Math.random() * 10 // 生成10以内的随机数
}
})结构为:
<view> {{ randomNum >= 5 ? '随机数字 >= 5' : '随机数字 < 5' }} </view>1.4.2 算数运算
页面的数据如下:
Page({
data: {
randomNum: Math.random().toFixed(2) // 生成一个带两位小数的随机数
}
})结构为:
<view>生成100以内的随机数 {{ randomNum * 100 }} </view>1.5 事件绑定
事件是 渲染层到逻辑层的通讯方式 。通过事件可以将用户在渲染层产生的行为,反馈到逻辑层进行业务的处理。

1.5.1小程序中常用的事件
| 事件类型 | 事件名称 | 触发时机 | 备注 |
|---|---|---|---|
tap 点击事件 | bindtap | 点击事件(冒泡) | 最常用的点击事件 |
catchtap | 点击事件(阻止冒泡) | 需阻止事件冒泡时使用 | |
bindlongpress | 长按事件 | 长按触发(冒泡) | |
catchlongpress | 长按事件(阻止冒泡) | 需阻止事件冒泡时使用 | |
touch 触摸事件 | bindtouchstart | 触摸开始 | 触摸交互相关 |
bindtouchmove | 触摸移动 | 触摸交互相关 | |
bindtouchend | 触摸结束 | 触摸交互相关 | |
bindtouchcancel | 触摸取消(如被其他事件打断) | ||
| 表单事件 | bindinput | 输入框内容实时变化 | 实时监听输入内容 |
bindchange | 输入框内容变化(失去焦点时触发) | 非实时监听 | |
bindfocus | 输入框获取焦点 | ||
bindblur | 输入框失去焦点 | ||
bindsubmit | 表单提交 | 需在 <form> 组件上绑定 | |
| 页面生命周期 | onLoad | 页面加载时触发(接收页面参数 options) | 页面初始化时调用 |
onShow | 页面显示时触发(每次打开页面都会调用) | ||
onReady | 页面初次渲染完成时触发(仅一次) | ||
onHide | 页面隐藏时触发(如跳转到其他页面) | ||
onUnload | 页面卸载时触发(如 redirectTo 或 navigateBack 关闭页面) | ||
onPullDownRefresh | 下拉刷新时触发(需在页面配置中启用 enablePullDownRefresh) | 下拉刷新功能 | |
onReachBottom | 上拉触底时触发(需配置 onReachBottomDistance) | 上拉加载更多功能 | |
onPageScroll | 页面滚动时触发(可获取滚动位置 scrollTop) | 滚动监听 |
事件类型说明:
tap点击事件- 包括普通点击 (
bindtap/catchtap) 和长按 (bindlongpress/catchlongpress)。 catch前缀会阻止事件冒泡到父组件。
- 包括普通点击 (
touch触摸事件- 用于更精细的触摸交互(如滑动、拖拽等)。
- 通常需要结合坐标计算实现自定义手势。
- 表单事件
- 监听输入框或表单的交互行为。
bindinput适合实时搜索,bindchange适合最终提交验证。
- 页面生命周期事件
- 控制页面加载、显示、隐藏等状态。
onPullDownRefresh和onReachBottom需在页面配置中启用。
1.5.2 事件对象的属性列表
当事件回调触发的时候,会收到一个事件对象 event ,它的详细属性如下表所示:
| 属性类别 | 属性名 | 类型 | 说明 | 适用场景 |
|---|---|---|---|---|
| 基础属性 | type | string | 事件类型(如 tap、input 等) | 所有事件 |
timeStamp | number | 事件生成时的时间戳(单位:毫秒) | 性能分析、事件计时 | |
target | object | 触发事件的组件的一些属性值集合 | 区分事件源 | |
currentTarget | object | 当前组件的一些属性值集合(可能不同于 target) | 事件冒泡时区分当前组件 | |
| 触摸事件特有 | touches | array | 当前停留在屏幕上的触摸点信息的数组 | touchstart/move/end |
changedTouches | array | 触摸事件中发生变化的触摸点信息的数组(如从无到有、位置变化等) | touchstart/move/end | |
| 表单事件特有 | detail | object | 额外的信息(如 input 事件的输入值、scroll 事件的滚动位置等) | input/scroll/form 等事件 |
| 自定义数据 | dataset | object | 事件源组件上由 data- 开头的自定义属性组成的对象 | 所有事件(组件间通信) |
| 其他 | touches[0].clientX touches[0].clientY | number | 触摸点的客户端屏幕坐标(X/Y) | 精确触摸位置计算 |
touches[0].pageX touches[0].pageY | number | 触摸点的页面坐标(含滚动偏移,X/Y) | 考虑页面滚动的触摸位置 | |
detail.x detail.y | number | 某些事件(如 scroll)的滚动位置坐标 | 滚动事件 |
1.5.3 target 和 currentTarget 的区别
target是触发该事件的源头组件 ,而 currentTarget 则是 当前事件所绑定的组件 。举例如下:

点击内部的按钮时,点击事件以冒泡 的方式向外扩散,也会触发外层 view 的 tap 事件处理函数。
此时,对于外层的 view 来说:
- e.target 指向的是触发事件的源头组件,因此, e.target 是内部的按钮组件
- e.currentTarget 指向的是当前正在触发事件的那个组件,因此, e.currentTarget 是当前的 view 组
1.5.4 bindtap 的语法格式
在 小程序中,不存HTML 中的 onclick 鼠标点击事件,而是通过 tap 事件 来响应用户的触摸行为。 ① 通过 bindtap ,可以为组件绑定 tap 触摸事件,语法如下:
<button type="primary" bindtap="btnTapHandler">按钮</button>② 在页面的 .js 文件中定义对应的事件处理函数,事件参数通过形参 eventevent(一般 简写成 e) 来接收:
Page({
btnTapHandler(e){
console.loe(e)
}
})1.5.5 在事件处理函数中为data中的数据赋值
通过调用 this.setData(dataObject) 方法,可以给页面data中的数据重新赋值:
// 页面的 .js 文件
Page({
data: {
count: 0
},
// 修改 count 的值
changeCount() {
this.setData({
count: this.data.count + 1
})
}
})更推荐将方法放在 methods 对象中(虽然直接定义在Page下也有效)
Page({
data: { count: 0 },
methods: {
changeCount() { // 更规范的写法
this.setData({ count: this.data.count + 1 })
}
}
})- 优势:代码组织更清晰,与Vue等框架风格一致。
1.5.6 事件传参
小程序中的事件传参比较特殊,不能在绑定事件的同时为事件处理函数传递参数 。例如,下面的代码将不能正常工作:
<button type="primary" bindtap="btnHandle(123)">事件传参</button>因为小程序会把 bindtap 的属性值,统一当作事件名称来处理,相当于要调用一个名称为 btnHandler(123)的事件处理函数。
正确的做法为,为组件提供 data-* 自定义属性传参,其中 * 代表参数名称:
<button bindtap="btnHandle" data-info="{{2}}">事件传参</button>最终:
- info 被解析为参数的名称
- 数值 2 被解析为参数的值
事件处理函数中,通过 event.target.dataset.参数名即可获取到具体参数的值:
btnHandle(event){
// dataset 是一个对象,包含了所有通过 data-* 传递过来的参数想
console.log(event.target.dataset)
// 通过 datase 可以访问到具体参数的值
console.log(event.target.dataset.info)
}1.5.7 bindinput 的语法格式
在小程序中,通过 input 事件 来响应文本框的输入事件,语法格式如下: ① 通过 bindinput ,可以为文本框绑定输入事件:
<input bindinput="inputHandler" />② 在页面的 .js 文件中定义事件处理函数:
inputHandler(e){
// e.detail.value 是变化过后,文本框的最新值
console.log(e.detail.value)
}1.5.8 实现文本框和 data 之间的数据同步
定义数据:
Page({
data:{
msg:'hello world'
}
})渲染结构:
<input value="{{msg}}" bindinput="iptHandler" />美化样式:
input {
border: 1px soild #eee;
padding: 5px;
margin: 5px;
border-redius: 3px;
}绑定 input 事件处理函数:
// 文本框内容改变事件
iptHandler(e){
this.setData({
// 通过 e.detail.value 获取到文本框的最新值
msg:e.detail.value
})
}当用户在输入框输入内容时:
- 小程序框架会自动触发
bindinput绑定的iptHandler函数。 - 框架会将一个事件对象
e作为参数传入iptHandler。 - 这个
e对象的detail.value属性已经包含了输入框的最新值(由小程序框架内部维护)。
1.6 条件渲染
1.6.1 wx:if
在小程序中,使用 wx:if="" 来判断是否需要渲染该代码块:
<view wx:if="{{condition}}">True</view>也可以使用 wx:elif 和 wx:else 添加判断分支:
<view wx:if="{{type === 1}}">男</view>
<view wx:elif="{{type === 2}}">女</view>
<view wx:else>保密</view>如果要一次性控制多个组件的展示与隐藏,可以使用一个 <block> 标签将多个组件包裹起来,并在 <block> 上使用 wx:if 控制:
<block wx:if="{{true}}">
<view>view</view>
<view>view</view>
</block>注意:
<block>并不是一个组件,它只是一个包裹性质的容器,不会在页面中做任何渲染。
1.6.2 hidden
小程序中,也可以使用 hidden="" 控制元素的显示与隐藏:
<view hidden="{{condition}}">条件为 true 隐藏,条件为 false 显示</view>wx:if 与 hidden 的对比
- 运行方式不同:
wx:if是以 动态创建和移除元素 的方式控制显示。hidden是以 切换样式(display: none/block) 的方式控制显示。
- 使用建议:
- 频繁切换时,建议使用
hidden。 - 条件复杂时,建议使用
wx:if搭配wx:elif和wx:else来控制展示与隐藏。
1.7 列表渲染
1.7.1 wx:for
通过 wx:for 可以根据指定的数组,循环渲染重复的组件结构:
<view wx:for="{{array}}">
索引是:{{index}} 当前项是:{{item}}
</view>默认情况下,当前循环项的索引 用 index 表示; 当前循环项 用 item 表示。
1.7.2手动指定索引和当前项的变量名 *
使用 wx:for for-index 可以指定 当前循环项的索引 的变量名
使用 wx:for for-item 可以指定 当前项 的变量名 示例代码如下:
html<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName"> 索引是:{{idx}} 当前项是:{{itemName}} </view>
1.7.3 wx:key 的使用
类似于 Vue 列表渲染中的 :key ,小程序在实现列表渲染时,也建议为渲染出来的列表项指定唯一的 key 值, 从而 提高渲染的效率 :
// data 数据
data: {
userList: [
{ id: 1, name: '小红' },
{ id: 2, name: '小黄' },
{ id: 3, name: '小白' }
]
}
<!-- wxml 结构 -->
<view wx:for="{{userList}}" wx:key="id">{{item.name}}</view>wxss 模板样式
2.1 基本概念
WXSS (WeiXin Style Sheets)是一套 样式语言 ,用于美化 WXML 的组件样式,类似于网页开发中的 CSS 。
WXSS 具有 CSS 大部分特性, 同时WXSS 还对 CSS 进行了扩充以及修改,以适应微信小程序的开发。 与 CSS 相比, WXSS 扩展的特性有:
- rpx 尺寸单位
- @import 样式导入
2.2 rpx
rpx(responsive pixel )是微信小程序独有的,用来 解决屏适配的尺寸单位 。
rpx的实现原理非常简单:鉴于不同设备屏幕的大小不同,为了实现屏幕的自动适配,rpx 把所有设备的屏幕,在宽度上等分为 750 份(即: 当前屏幕的总宽度为 750rpx)。
- 在较小 的设备上, 1rpx 所代表的宽度较小
- 在较大 的设备上, 1rpx 所代表的宽度较大
小程序在不同设备上运行的时候,会自动把rpx 的样式单位换算成对应的像素单位来渲染,从而实现屏幕适配。
2.3 rpx 与 px 之间的单位换算
rpx 与 px 的核心区别
| 单位 | 全称 | 特点 | 适用场景 |
|---|---|---|---|
| rpx | responsive pixel(响应式像素) | 根据屏幕宽度自动缩放,保证不同设备显示比例一致 | 小程序中推荐优先使用,尤其是需要适配多种屏幕的场景(如布局、字体大小) |
| px | pixel(物理像素) | 固定物理像素值,不随屏幕变化 | 用于需要精确控制像素的场景(如边框、阴影等细节) |
rpx 与 px 的换算规则
小程序的 rpx 设计目标是:在所有设备上,750rpx 恰好等于屏幕宽度。 因此,换算公式为:
rpx=px×设计稿宽度(px)750
或反向换算:
px=rpx×750设计稿宽度(px)
常见场景示例:
- 以 750px 宽度的设计稿为准(小程序官方推荐设计稿宽度):
- 1px(设计稿) = 1rpx(小程序) (因为
750rpx = 750px,所以1rpx = 1px) - 例如:设计稿中一个按钮宽度为
150px,则小程序中直接写width: 150rpx。
- 1px(设计稿) = 1rpx(小程序) (因为
- 以其他宽度(如 375px)的设计稿为准:
- 换算公式:
1px(设计稿) = 2rpx(小程序)(因为750rpx = 375px,所以1rpx = 0.5px,即1px = 2rpx) - 例如:设计稿中一个元素高度为
100px,则小程序中需写height: 200rpx。
- 换算公式:
2.4 样式导入
使用 WXSS 提供的 @import 语法,可以导入外联的样式表。
@import 后跟需要导入的外联样式表的 相对路径 ,用 ;表示语句结束,示例如下:
//** common.wxss **//
.small-p {
padding: 5px;
}//** app.wxss **//
@import "common.wxss"
.middle-p {
padding: 5px;
}2.5 全局样式和局部样式
定义在 app.wxss 中的样式为全局样式 ,作用于每一个页面。
在页面的 .wxss 文件中定义的样式为局部样式 ,只作用于当前页面。
注意:
① 当局部样式和全局样式冲突时,根据 就近原则 ,局部样式会 覆盖 全局样式
② 当局部样式的 权重大于或等于 全局样式的权重时,才会覆盖全局的样式