语法
WXML 语法
对比 HTML 语法,WXML 语法除了标签/组件存在差异以外,渲染界面的方式也不一样。WXML 具有以下几种能力:
- 数据绑定
- 条件渲染
- 列表渲染
- 模板
- 引用
无论是数据绑定、条件渲染还是列表渲染,我们都需要用到页面中的 js 文件。我们可以打开任意一个页面文件夹下的 js 文件,都可以看到以下的这种结构:
// pages/page2/page2.js
Page({
/* 页面的初始数据 */
data: {
},
/* 生命周期函数--监听页面加载 */
onLoad(options) {
},
/* 生命周期函数--监听页面初次渲染完成 */
onReady() {
},
/* 生命周期函数--监听页面显示 */
onShow() {
},
/* 生命周期函数--监听页面隐藏 */
onHide() {
},
/* 生命周期函数--监听页面卸载 */
onUnload() {
},
/* 页面相关事件处理函数--监听用户下拉动作 */
onPullDownRefresh() {
},
/* 页面上拉触底事件的处理函数 */
onReachBottom() {
},
/* 用户点击右上角分享 */
onShareAppMessage() {
}
})
Page()
是一个页面构造器,作用就是注册小程序中的一个页面。它接受一个 Object 类型参数,其指定页面的初始数据、生命周期回调、事件处理函数等。
data
是页面第一次渲染使用的初始数据。页面加载时,data
将会以 JSON 字符串的形式由逻辑层传至渲染层,因此 data
中的数据必须是可以转成 JSON 的类型:字符串,数字,布尔值,对象,数组。渲染层可以通过 WXML 对数据进行绑定。例如:
<view>{{text}}</view>
<view>{{array[0].msg}}</view>
Page({
data: {
text: 'init data',
array: [{msg: '1'}, {msg: '2'}]
}
})
1. 数据绑定
数据绑定使用 Mustache
语法(双大括号{{ }}
),Mustache
语法是一种简单的模板语言,它使用大括号语法{{}}
来进行变量替换和逻辑控制,例如:
//index.js
Page({
data: {
message: "Hello, 微信小程序"
}
})
<!--index.wxml-->
<view> {{ message }} </view>
微信小程序是通过状态模式进行数据绑定的。状态模式定义一个对象,通过管理其状态的变化,从而让界面做出相应的变化。
简单地讲,只要对象状态发生变化,就通知页面更新视图元素。 通过以下三个步骤 可以实现:
- 识别哪个 UI 元素被绑定了相应的对象
- 监视对象状态的变化
- 将所有变化传播到绑定的视图上
.wxml
文件中的动态数据均来自对应页面的 .js
文件中 Page
的 data
对象。 一旦 data 对象中的数据发生变化,界面就会发生相应的变化。
绑定数据可以作用于三个位置 - 内容
、组件属性
和 控制属性
,而且还可以处理一些关键字。
内容
:<view> {{message}} </view>
//index.js Page({ data: { message: "Hello, 微信小程序" } })
组件属性
(需要在双引号内):<!--index.wxml--> <view class="box box-{{color}}"></view> <view class="box box-{{color2}}"></view>
//index.js Page({ data: { color: "blue", color2: "red" } })
/* pages/index/index.wxss */ .box { weight: 200rpx; height: 50rpx; } .box-blue { background-color: blue; } .box-red { background-color: red; }
控制属性
(需要在双引号之内):<!--index.wxml--> <view wx:if=”{{condition}}”> </view>
//index.js Page({ data: { condition: false } })
wx:if
是条件渲染用到的语法,后面会介绍到。.wxml
文件中常用的关键字有 true、false,是 boolean 类型,分别表示真和假。
其实我们可以在 Mustache (双大括号如 {{ }}
)内进行简单的运算,支持下面几种方式:
算数运算
<!--index.wxml--> <view> {{a + b}} + {{c}} + d </view> <view> {{ name + id }} </view>
//index.js Page({ data: { a: 1, b: 2, c: 3, name: "罗大富", id: 123456 } })
数据路径运算
//index.js Page({ data: { array: [1, 2, 3, 4, 5, 6], student: { name: "罗大富" } } })
2. 列表渲染 - wx:for
相信大家都有过网上购物的经历,我们打开任意一个网购平台,就可以看到数不完的商品。对于前端工程师来说,每个商品他就对应了很多品牌和型号,那我们就需要把每个品牌对应的一个商品信息展示给用户。当我们商品数量比较小的时候,我们可以去一行一行的写类似的 wxml 标签。但是如果说我们的商品数量比较多,而且商品数量不固定的时候。那我们肯定不能这样一行一行的去写 wxml 标签了,这个时候,我们就需要用到微信小程序中的列表渲染。
在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。默认数组的当前项的下标变量名默认为 index
,数组当前项的变量名默认为 item
,例如:
<view wx:for="{{array}}">
{{index}}: {{item}}
</view>
Page({
data: {
array: ['a', 'b', 'c', 'd', 'e', 'f', 'g']
}
})
我们可以使用 wx:for-item 可以指定数组当前元素的变量名,使用 wx:for-index 可以指定数组当前下标的变量名:
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="name">
{{idx}}: {{name}}
</view>
如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 input 中的输入内容,switch 的选中状态),需要使用 wx:key
来指定列表中项目的唯一的标识符。
wx:key
的值以两种形式提供:
- 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
- 保留关键字
*this
代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。
当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。
:::tips
如不提供 wx:key
,会报一个 warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。
:::
block 标签
学习完控制属性 wx:for
之后,我们还需要补充一个小的知识点 block 标签,这个标签比较特殊。在写代码的时候,他是存在的,但是不会渲染在页面上,最终不能成为真正的 DOM 元素。
<view>
<view wx:for="{{array}}">
{{index}}: {{item}}
</view>
</view>
如果把上方代码中的 view 替换成 block,如下:
<view>
<block wx:for="{{array}}">
{{index}}: {{item}}
</block>
</view>
页面中就会出现一个 view 标签包裹着所有的循环内容,我们可以简单的把 block 标签理解为是一个占位符,在写代码的时候,我们可以看到。但是在页面中,就会被移除掉。
当你要使用列表、条件渲染某些数据的时候,如果不想额外添加一层节点(或者说标签),我们就可以使用 block 标签起到一层占位的作用。
:::tips <block/>
并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。 :::
3. 条件渲染 - wx:if
在框架中,使用 wx:if=""
来判断是否需要渲染该代码块:
<view wx:if="{{condition}}"> True </view>
也可以用 wx:elif
和 wx:else
来添加一个 else
块:
<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>
因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。
<block wx:if="{{true}}">
<view> view1 </view>
<view> view2 </view>
</block>
wx:if vs hidden
因为 wx:if
之中的模板也可能包含数据绑定,所以当 wx:if
的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。
同时 wx:if
也是惰性的,如果在初始渲染条件为 false
,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。
相比之下,hidden
就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。
一般来说,wx:if
有更高的切换消耗而 hidden
有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden
更好,如果在运行时条件不大可能改变则 wx:if
较好。