其他相关文章
从0到一开发微信小程序(1)——申请账号并安装开发环境
从0到一开发微信小程序(2)——开发第一个小程序
从0到一开发微信小程序(3)—小程序框架配置
从0到一开发微信小程序(4)—小程序组件
从0到一开发微信小程序(5)—小程序WXML
从0到一开发微信小程序(6)—小程序常用API
从0到一开发微信小程序(7)—小程序组件库(提高开发效率)
从0到一开发微信小程序(8)—实战一个商城项目——正在书写中
1、WXML
首先,我们得看看wxml是什么?
WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。
1.1、事件
1.1.1、系统
什么是事件?
- 事件是视图层到逻辑层的通讯方式。
- 事件可以将用户的行为反馈到逻辑层进行处理。
- 事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
- 事件对象可以携带额外信息,如 id, dataset, touches。
怎么使用呢?
- 在组件中绑定一个事件处理函数。
如bindtap,当用户点击该组件的时候会在该页面对应的 Page 中找到相应的事件处理函数。
测试代码:
<view id="tapTest" data-hi="Weixin" bindtap="tapName"> Click me! </view>
Page({
tapName: function(event) {
console.log(event)
}
})
展示效果:
点击之后,控制栏会出现:
上图中各个属性值的详细分析如下:
属性 | 类型 | 说明 |
---|---|---|
type | String | 事件类型 |
timeStamp | Integer | 事件生成时的时间戳 |
target | Object | 触发事件的组件的一些属性值集合 |
currentTarget | Object | 当前组件的一些属性值集合 |
mark | Object | 事件标记数据 |
detail | Object | 额外的信息 |
touches | Array | 触摸事件,当前停留在屏幕中的触摸点信息的数组 |
changedTouches | Array | 触摸事件,当前变化的触摸点信息的数组 |
1.1.2、分类
事件主要分类为两个种:一种是冒泡事件,一种是非冒泡事件:
- 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
- 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。
1.1.2.1、冒泡事件(bindtap)
- 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 设备,重按时会触发 |
测试用例:
<view bindtap="bindParentBubbleHandle">
<button type="primary" bindtap="bindChildBubbleHandle">冒泡事件</button>
</view>
Page({
bindParentBubbleHandle(){
console.log("父级冒泡事件");
},
bindChildBubbleHandle(){
console.log("子级冒泡事件");
}
})
展示效果:
点击冒泡事件,控制台展示为:
1.1.2.2、非冒泡事件(catchtap)
测试用例:
<view catchtap="catchParentBubbleHandle">
<button type="primary" catchtap="catchChildBubbleHandle">非冒泡事件</button>
</view>
catchParentBubbleHandle(){
console.log("非冒泡父级事件");
},
catchChildBubbleHandle(){
console.log("非冒泡子级事件");
}
展示效果:
点击非冒泡事件,控制台展示为:
1.1.3、携带参数
1.1.3.1、currentTarget 携带参数
- 在组件节点中可以附加一些自定义数据。这样,在事件中可以获取这些自定义的节点数据,用于事件的逻辑处理。
属性 | 类型 | 说明 |
---|---|---|
id | String | 当前组件的id |
dataset | Object | 当前组件上由data-开头的自定义属性组成的集合 |
测试代码:
<view data-id="1001" bindtap="bindViewTap"> 携带参数 </view>
Page({
bindViewTap(e){
console.log(e.currentTarget.dataset.id);
}
})
展示效果:
当我们点击携带参数,会发现控制栏会出现
说明我们e.currentTarget.dataset.id获取到了id的值
温馨提示
在wxml中添加数据的时候,必须在自定义属性前添加data-*
1.1.3.2、mark读取携带参数
- 可以使用 mark 来识别具体触发事件的 target 节点。此外, mark 还可以用于承载一些自定义数据(类似于 dataset )。
- 当事件触发时,事件冒泡路径上所有的 mark 会被合并,并返回给事件回调函数。(即使事件不是冒泡事件,也会 mark 。)
测试代码:
<view mark:parentMark="父级" bindtap="bindMarkTap">
<button type="primary" mark:childMark="子级" bindtap="bindButtonTap">mark读取携带参数</button>
</view>
bindMarkTap(e) {
console.log(e.mark);
},
bindButtonTap(e) {
console.log(e.mark);
}
展示效果:
点击mark读取携带参数会发现控制栏出现:
mark 和 dataset 很相似,主要区别在于: mark 会包含从触发事件的节点到根节点上所有的 mark: 属性值;而 dataset 仅包含一个节点的 data- 属性值。
细节注意事项:
- 如果存在同名的 mark ,父节点的 mark 会被子节点覆盖。
- 在自定义组件中接收事件时, mark 不包含自定义组件外的节点的 mark 。
- 不同于 dataset ,节点的 mark 不会做连字符和大小写转换。
1.1.3.3、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 // 大写会转为小写
}
})
1.2、条件
条件判断,相信大家只要玩过后端的基本都知道吧,前端vue也是如此。
1.2.1、wx:if(如果)
<view wx:if="{{ flag }}">你帅吗</view>
Page({
data: {
flag:true //展示
}
})
展示效果:
1.2.2、wx:else(那么)
<view wx:if="{{ flag }}">我帅</view>
<view wx:else="{{ flag }}">你丑</view>
Page({
data: {
flag:true //展示
}
})
展示效果:
1.2.3、wx:elif(如果那么)
<view wx:if="{{length === 1}}"> 1 </view>
<view wx:elif="{{length === 2}}"> 2 </view>
<view wx:else>未知</view>
Page({
data: {
length:2
}
})
展示效果:
1.2.4、hidden(隐藏)
- hidden 与wx:if类似,同样可以来判断是否需要渲染该代码块
<view hidden="{{ hidden }}">果子熟了</view>
Page({
data: {
hidden:true
}
})
展示效果为空,因为已经隐藏了。
1.2.5、总结(wx:if vs hidden 区别)
因为 wx:if 之中的模板也可能包含数据绑定,所以当 wx:if 的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。
同时 wx:if 也是惰性的,如果在初始渲染条件为 false,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。
相比之下,hidden 就简单的多,组件始终会被渲染,只是简单的基于CSS控制显示与隐藏。
一般来说,wx:if 有更高的切换消耗而 hidden 有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden 更好,如果在运行时条件不大可能改变则 wx:if 较好
1.3、列表渲染–循环遍历
- 在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件
基本使用
默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item
测试代码:
<view>
<view wx:for="{{ moves }}">{{ item }}</view>
</view>
Page({
data: {
moves:["西游记","三国演义","爱情公寓"]
}
})
展示效果:
带下标输出的使用
- 使用 wx:for-item 可以指定数组当前元素的变量名
- 使用 wx:for-index 可以指定数组当前下标的变量名
测试代码:
<view>
<view wx:for="{{ moves }}" wx:for-item="move" wx:for-index="id">{{id}}-{{ move }}</view>
</view>
Page({
data: {
moves:["西游记","三国演义","爱情公寓"]
}
})
展示效果:
复杂数据(Json)
<view>
<block wx:for="{{ result }}" wx:for-item="item">
<view>{{ item.name }}</view>
<image src="{{ item.pic }}"></image>
<view>{{ item.description }}</view>
<view>{{ item.price }}</view>
<view>{{ item.city }}</view>
</block>
</view>
Page({
data: {
result: [{
"id": 1,
"name": "美食-甜豆干",
"pic": "http://iwenwiki.com:3002/images/goods/1.jpg",
"description": "津津卤汁豆腐干苏州特产豆干零食素食老字号食品豆制品小吃90g*10",
"price": "39.90",
"type": 0,
"buynum": "435",
"city": "北京"
},
{
"id": 2,
"name": "好欢螺螺蛳粉300g*6袋",
"pic": "http://iwenwiki.com:3002/images/goods/2.jpg",
"description": "好欢螺螺蛳粉300g*6袋柳州特产螺狮粉美食螺丝粉煮水方便面酸辣粉",
"price": "69.99",
"type": 0,
"buynum": "3333",
"city": "北京"
}
]
}
})
展示效果:
1.3.1、wx:key(唯一标识符)
- 如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态,需要使用 wx:key 来指定列表中项目的唯一的标识符
- 当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率
温馨提示:
如不提供 wx:key,会报一个 warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略
当我们想数组中添加新的数据,并且放在首位的时候,在渲染的时候,key就起到了作用
测试用例:
<view>
<button type="primary" bindtap="clickHandle">增加数据</button>
<block wx:for="{{ result }}" wx:for-item="item" wx:key="id">
<view>{{ item.name }}</view>
<image src="{{ item.pic }}"></image>
<view>{{ item.description }}</view>
<view>{{ item.price }}</view>
<view>{{ item.city }}</view>
</block>
</view>
Page({
data: {
result: [{
"id": 1,
"name": "美食-甜豆干",
"pic": "http://iwenwiki.com:3002/images/goods/1.jpg",
"description": "津津卤汁豆腐干苏州特产豆干零食素食老字号食品豆制品小吃90g*10",
"price": "39.90",
"type": 0,
"buynum": "435",
"city": "北京"
},
{
"id": 2,
"name": "好欢螺螺蛳粉300g*6袋",
"pic": "http://iwenwiki.com:3002/images/goods/2.jpg",
"description": "好欢螺螺蛳粉300g*6袋柳州特产螺狮粉美食螺丝粉煮水方便面酸辣粉",
"price": "69.99",
"type": 0,
"buynum": "3333",
"city": "北京"
}
]
},
clickHandle(){
this.setData({
result:this.data.result.concat({
"id":"3",
"name": "对夹",
"pic": "http://iwenwiki.com:3002/images/goods/1.jpg",
"description": "津津卤汁豆腐干苏州特产豆干零食素食老字号食品豆制品小吃90g*10",
"price": "39.90",
"type": 0,
"buynum": "435",
"city": "北京"
})
})
}
})
展示效果:
最下面一条数据为:
当点击增加数据之后,会增加一条数据展示:
1.3.2、应用
- 轮播图
- 查询页面
轮播图实例:
<swiper
indicator-dots
indicator-color="#fff"
indicator-active-color="#f00"
autoplay
>
<block wx:for="{{ swiperData }}" wx:for-item="item" wx:for-index="index" wx:key="index">
<swiper-item>
<image mode="widthFix" style="width: 100%;" src="{{ item }}"></image>
</swiper-item>
</block>
</swiper>
swiperData:[
"http://iwenwiki.com:3002/images/goods/1.jpg",
"http://iwenwiki.com:3002/images/goods/2.jpg",
]
展示效果为滑动轮播图。
1.4、模板(提高复用性)
- 模板顾名思义就是一个可以多处使用的代码。
- WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用
定义模板
首先总体文件结构如下:
首先定义模板,图片中的list下面的文件就是模板,模板只有两种文件,wxml,wxss。
list.wxml的内容为:
<template name="customTemplate">
<view class="text">{{ test }}</view>
</template>
list.wxss的内容为:
.text{
color: red;
}
真正的内容来了:
template.js文件的内容为:
Page({
data: {
test:"测试"
}
})
template.wxml文件的内容为:
<import src="./list/list.wxml" />
<view>
<view>引用模板</view>
<template is="customTemplate" data="{{ test }}"></template>
<template is="customTemplate" data="{{ test }}"></template>
</view>
template.wxss文件的内容为:
@import "./list/list.wxss";
展示效果:
模板运用(列表复用)
文件目录如下:
list.wxml文件的内容如下:
<template name="listTemplate" >
<view class="list">
<block wx:for="{{ foods }}" wx:for-item="item" wx:key="id">
<view class="item">
<image mode="widthFix" src="{{ item.pic }}"></image>
<text>{{ item.name }}</text>
</view>
</block>
</view>
</template>
list.wxss文件的内容如下:
.list{
width: 100%;
}
.item{
margin: 10px;
}
.list image{
width: 100px;
}
list-template.js文件的内容如下:
Page({
data: {
foods: [{
"id": 1,
"name": "美食-甜豆干",
"pic": "http://iwenwiki.com:3002/images/goods/1.jpg"
},
{
"id": 2,
"name": "好欢螺螺蛳粉300g*6袋",
"pic": "http://iwenwiki.com:3002/images/goods/2.jpg"
},
{
"id": 3,
"name": "良品铺子-肉松饼380gx2袋",
"pic": "http://iwenwiki.com:3002/images/goods/3.webp"
}
]
}
})
list-template.wxml文件的内容如下:
<import src="./list/" />
<template is="listTemplate" data="{{ foods }}"></template>
list-template.wxss文件的内容如下:
@import "./list/list.wxss";
展示效果为:
有兴趣可以加知识星球:(每日打卡,每日一题,Java,前端)
我是zhz小白,一个在互联网行业的小白,立志成为一名架构师
https://blog.csdn.net/zhouhengzhe?t=1