WXML 中的动态数据均来自对应 Page 的 data。
数据绑定使用 Mustache 语法(双大括号)将变量包起来,可以作用于许多地方。
# 一、数据绑定
其实小程序中的Mustache 语法和 vue 中的插值表达式类似
vud 中的插值表达式使用位置只能在内容节点,不能在属性节点。
小程序的 Mustache 语法既可以使用于内容节点,还可以使用于属性节点。
# 1、内容渲染
<view> {{ text-message }} </view>
<rich-text nodes="{{html-message}}"></rich-text>
Page({
data: {
text-message: "纯文本",
html-message: "HTML标签字符串"
}
})
在 vue 中则是通过 v-text、v-html 属性和文本插值实现
Mustache 语法使用:
<!-- 运算 -->
<div>{{ number + 1 }}</div>
<!-- 三元运算 -->
<view hidden="{{flag ? true : false}}"> Hidden </view>
<!-- 非字符串类型、关键字👀 -->
<checkbox checked="{{false}}"> </checkbox>
<!-- 数组和对象中👀 -->
<view wx:for="{{[zero, 1, 2, 3, 4]}}"> {{item}} </view>
<template is="objectCombine" data="{{for: a, bar: b}}"></template>
<template is="objectCombine" data="{{foo, bar}}"></template>
<!-- 拼接🍗 -->
<div id="{{'list-' + id}}"></div>
# 2、属性绑定
从上面的代码示例可以发现,在小程序中进行属性绑定时,不需要在属性前加上 v-bind
(:),而是直接使用 Mustache 语法即可。
在小程序中几乎关系数据绑定的使用的都是 Mustache 语法
提示
花括号和引号之间如果有空格,将最终被解析成为字符串
<swiper>
<block wx:for="{{banners}}" wx:key="image">
<swiper-item>
<view class="swiper-item {{item}}"></view>
</swiper-item>
</block>
</swiper>
# 3、变量赋值
Page.prototype.setData(Object data, Function callback)
setData 函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data 的值(同步)
// index.js
Page({
data: {
text: 'init data',
num: 0,
array: [{ text: 'init data' }],
object: {
text: 'init data'
}
},
// 1、若修改this.data(视图不会更新)
changeText: function () {
// this.data.text = 'changed data' // ✖
// 【对于一些没有视图更新需求的数据,是可以直接这样写的,简洁👀】
},
// 2、可以在函数内修改后赋值
changeNum: function () {
this.data.num = 1
this.setData({
num: this.data.num
})
},
// 3、数组和对象中的赋值
changeItemInArray_Object: function () {
this.setData({
'array[0].text': 'changed data',
'object.text': 'changed data'
})
}
})
# 4、template 模板 ✨
官方文档:
提示
自从基础库版本 1.6.3 开始支持自定义组件开发后,使用 template 模板的频率就变得相对较少了 🤔。
① 代码示例
- 定义模板
<!-- name属性作为模板的名字 -->
<template name="msgItem">
<view>
<text> {{index}}: {{msg}} </text>
<text> Time: {{time}} </text>
</view>
</template>
- 使用模板
<!-- 使用is属性指定使用的模板 -->
<template is="msgItem" data="{{...item}}" />
② is 属性拓展
is 属性可以使用 Mustache 语法,来动态决定具体需要渲染哪个模板
<template name="odd">
<view> odd </view>
</template>
<template name="even">
<view> even </view>
</template>
<block wx:for="{{[1, 2, 3, 4, 5]}}">
<template is="{{item % 2 == 0 ? 'even' : 'odd'}}" />
</block>
# 二、事件处理
# 1、事件绑定
小程序中的事件绑定和 vue 中的事件绑定有很大的不同。
- vue 中:
<!-- 不带参 -->
<button v-on:click="myFunction">点击我.</button>
<p id="demo" @click="myFunction">点击我.</p>
<!-- 带参 -->
<button @click="add($event, 1)">+N</button>
- 小程序中:
<!-- 不带参 -->
<button bind:tap="myFunction">点击我.</button>
<p id="demo" bindtap="myFunction">点击我.</p>
<!-- 带参 -->
<button bindtap="add" data-num="{{1}}">+N</button>
data-num 属性:num 表示参数名
可以发现 vue 中的事件绑定采用v-on
,而小程序中采用bind:
;并且在事件传参上的使用是不同的。
传参变化原因
根本原因就是小程序采用的是双线程模型,我们不能直接在逻辑层使用逻辑层传来的数据。
但我们可以巧妙的借助自定义属性实现解决这个问题。
① 小程序常用事件:
事件类型 | 事件绑定 | 说明 |
---|---|---|
tap | bindtap | 触摸后离开(类似于 HTML 中的 click) |
input | bindinput | 文本框输入事件 |
change | bindchange | 状态改变时触发 |
对于事件的具体使用,详见组件 (opens new window)
# 2、event 对象
相较于 vue,在小程序中使用原生事件对象 event 的频率会高很多。
因为事件传参是通过 自定义属性
data-*
进行传递的。
注意
由于事件参数也绑定到了 event 对象上,当我们要拿取事件参数时,记得使用 event.currentTarget,而不是 event.target
如果实在区分不了,在基础库版本 2.7.1 以上时,我们还可以使用
mark:*
进行传参。
myFunction(e) {
console.log(e)
console.log(e.target.dataset) // 触发事件的源组件的参数集合
console.log(e.detail.value) // value属性值变化🚩(数据传递👀)
console.log(e.mark) // 仅小程序中
// 冒泡事件中
console.log(e.currentTarget.dataset) // 当前事件绑定的组件的参数集合
}
# 3、捕获与冒泡
除 bind 外,也可以用 catch 来绑定事件。与 bind 不同, catch 会阻止事件向上冒泡。
需要在捕获阶段监听事件时,可以采用 capture-bind
、capture-catch 关键字,后者将中断捕获阶段和取消冒泡阶段。
# 三、条件渲染
# 1、使用示例
<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>
可以发现,小程序中使用
vx:
代替了 vue 中的v-
拓展:
如果要一次性判断多个组件标签,可以使用一个 <block/>
标签将多个组件包装起来,并在上边使用 wx:if 控制属性。
<block wx:if="{{true}}">
<view> view1 </view>
<view> view2 </view>
</block>
<block/>
并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。
# 2、显示与隐藏
<view wx:if="{{flag}}">wx:if控制的内容区域</view>
<view hidden="{{flag}}">hidden控制的内容区域</view>
对于使用选择,可以联系到 vue 中的:
v-if
类似于小程序中的wx:if
v-show
类似于小程序中的hidden
# 四、列表渲染
小程序中的列表渲染和 vue 中的列表渲染有很大的不同。
Page({
data: {
// 一个数组
items: [
{ message: '1', message2: 'Foo'},
{ message: '2', message2: 'Bar'},
// ……,
]
// 单个对象
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publish: '2016-04-10'
}
}
})
# 1、使用示例
- vue 中
<!-- 1、数组 -->
<ul id="example-1">
<li v-for="(item, index) in items" :key="item.message">{{ item.message }}</li>
</ul>
<!-- 2、对象 -->
<ul id="example-2">
<li v-for="(value, name, index) in object">{{ index }}. {{ name }}: {{ value }}</li>
</ul>
- 小程序中
<!-- 1、数组 -->
<view id="example-1">
<view wx:for="{{items}}" wx:key="message">{{index}}:{{item.message}}</view>
</view>
<!-- 2、数字、字符串 -->
<view id="example-2">
<view wx:for="{{10}}" wx:key="*this">{{item}}</view>
</view>
通过对比发现,在小程序中直接将 🚩 数组名挂载即可,并且相应的index
、item
、可以直接使用
- index:数组当前项下的默认标变量名
- item:数组当前项的默认变量名
注意:
wx:key
的使用不需要使用插值表达式
# 2、wx:key 使用
wx:key 值的两种形式
字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。
提示
小程序中也提供了类似于 vue 中的<template></template>
标签的组件 —— <block></block>
<block wx:for="{{[1, 2, 3, 4, 5]}}" wx:key="*this">
<view>{{item % 2 == 0 ? 'even' : 'odd'}}</view>
</block>
# 3、双层 for
小程序默认将遍历的没一项命名为 item,在多层 for 循环中,我们是可以对其命名进行修改的
wx:for-item="i"
、wx:for-index="itemIndex"
<view>
<block wx:for="{{list}}" wx:key="index">
<view>{{item}}</view>
<block wx:for="{{list.data}}" wx:key="*this" wx:for-item="i">
<view>{{i}}</view>
</block>
</block>
</view>
# 五、双向绑定
在 WXML 中,普通的属性的绑定是单向的。如:
① 简单示例
- 单向
<input value="{{value}}" />
- 双向
<input model:value="{{value}}" />
② 注意事项
双向绑定的表达式只能是一个单一字段的绑定,并且不然识别 data 路径
- 错误示例
<input model:value="值为 {{value}}" />
<input model:value="{{ a + b }}" />
<input model:value="{{ a.b }}" />