小程序的组件和api和事件

小程序的组件和api

组件

1
2
3
https://developers.weixin.qq.com/ebook?action=get_post_info&docid=000eec0b998e80bb0086f092b5100a
一个小程序页面可以分解成多个部分组成,组件就是小程序页面的基本组成单元。为了让开发者可以快速进行开发,小程序的宿主环境提供了一系列基础组件。
组件是在WXML模板文件声明中使用的,WXML的语法和HTML语法相似,小程序使用标签名来引用一个组件,通常包含开始标签和结束标签,该标签的属性用来描述该组件。

组件共有属性

1
2
3
4
5
6
7
属性名	类型	描述	其他说明
id String 组件的唯一标示 保持整个页面唯一
class String 组件的样式类 在对应的WXSS中定义的样式类
style String 组件的内联样式 可以通过数据绑定进行动态设置的内联样式
hidden Boolean 组件是否显示 所有组件默认显示
data-* Any 自定义属性 组件上触发的事件时,会发送给事件处理函数
bind / catch EventHandler 事件 详情见3.5

自定义组件

新建文件夹(所有组件component)
里面,新建组件文件夹(swiper)
里面,新建组件文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
swiper.wxml
<view class="inner">
{{innerText}}
</view>
swiper.wxss
.inner {
color: red;
}
swiper.json
{
"component": true
}
swiper.js
Component({
properties: {
// 这里定义了innerText属性,属性值可以在组件使用时指定
innerText: {
type: String,
value: 'default value',
}
},
data: {
// 这里是一些组件内部数据
someData: {}
},
methods: {
// 这里是一个自定义方法
customMethod: function(){}
}
})

组件的引用
seiper 任意组件名字
page1.json(需要引用组建的页面)

1
2
3
4
5
6
7
8
9
10
{
"usingComponents": {
"seiper": "../component/swiper/swiper"
}
}
page1.wxml(需要引用组建的页面)
<view>
<!-- 以下是对一个自定义组件的引用 -->
<seiper inner-text="Some text"></seiper>
</view>

swiper组件 案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
swiper.wxml
<!--pages/component/swiper/swiper.wxml-->
<view class="page-body">
<view class="page-section page-section-spacing swiper">
<swiper
indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" circular="{{circular}}" vertical="{{vertical}}"
interval="{{interval}}" duration="{{duration}}" previous-margin="{{previousMargin}}px" next-margin="{{nextMargin}}px">
<block wx:for="{{background}}" wx:key="*this">
<swiper-item>
<view>
<image src="/pages/img/1-s-benner.png"></image>
</view>
</swiper-item>
</block>
</swiper>
</view>
</view>



swiper.js
const app = getApp()

Page({
data: {
motto: 'Hello World',
userInfo: {},
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
background: ['demo-text-1', 'demo-text-2', 'demo-text-3'],
indicatorDots: true,
vertical: false,
autoplay: true,
circular: true,
interval: 3000,
duration: 500,
previousMargin: 0,
nextMargin: 0
},
})

swiper.json
{
"component": true,
"usingComponents": {}
}
swiper.wxss
/* pages/component/swiper/swiper.wxss */
/* @import "./weui.wxss"; */

page {
background-color: #F8F8F8;
height: 100%;
font-size: 32rpx;
line-height: 1.6;
}
.page-body{
background-color: pink;
}
.page-section{
width: 100%;
}
.page-section_center{
display: flex;
flex-direction: column;
align-items: center;
}
.page-section:last-child{
margin-bottom: 0;
}
.page-section-gap{
box-sizing: border-box;
padding: 0 30rpx;
}
.page-section-spacing{
box-sizing: border-box;
}
.page-section-title{
font-size: 28rpx;
color: #999999;
margin-bottom: 10rpx;
padding-left: 30rpx;
padding-right: 30rpx;
}
.page-section-gap .page-section-title{
padding-left: 0;
padding-right: 0;
}
button{
margin-bottom: 30rpx;
}
button:last-child{
margin-bottom: 0;
}
.page-section-title{
padding: 0;
}
swiper{
height: 370rpx;
}
swiper-item{
display: block;
height: 100%;
width: 100%;
}
swiper-item >view{
width: 100%;
height: 100%;
}
swiper-item >view image{
width: 100%;
height: 100%;
}
.page-section-title{
margin-top: 60rpx;
position: relative;
}
.info{
position: absolute;
right: 0;
color: #353535;
font-size: 30rpx;
}
.page-foot{
margin-top: 50rpx;
}

三级联动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
https://developers.weixin.qq.com/miniprogram/dev/component/picker.html
wxml
<picker mode="region" bindchange="bindRegionChange" value="{{region}}" custom-item="{{customItem}}">
<view class="picker">
<!-- 当前选择:{{region[0]}}{{region[1]}}{{region[2]}} -->
{{region[1]}}
</view>
</picker>
js
data: {
region: ['广东省', '广州市', '海珠区'],
customItem: '全部'
},
bindRegionChange: function (e) {
console.log('picker发送选择改变,携带值为', e.detail.value)
this.setData({
region: e.detail.value
})
},


就可以了
mode可以选择不同类型
multiSelector time date region(地区选择器)

组件传值

组件传值(父传子)

页面A

1
2
3
4
5
6
7
8
9
10
11
12
wxml
<titleimg paramAtoB="/pages/img/1-s-xinpintuijian.png"></titleimg>
paramAtoB 任意参数名
json
{
"usingComponents": {
"swiper": "/pages/component/swiper/swiper",
"navbox": "/pages/component/navbox/navbox",
"titleimg": "/pages/component/titleimg/titleimg"
}
}

组件页面B

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
wxml
<view class="titleimg">
<image mode='widthFix' src="{{paramAtoB}}"></image>
</view>
直接使用
js
Component({
behaviors: [],
properties: {
paramAtoB: String
},
data: {

}, // 私有数据,可用于模版渲染
// 生命周期函数,可以为函数,或一个在methods段中定义的方法名

attached: function () { },
moved: function () { },
detached: function () { },
methods: {

}

组件传值(子传父)

子组件内部准备参数

html

1
2
3
4
5
6
7
8
9
<view class="navbox">
<view class="navbox_ul" >
<view bindtap="tap_fn" data-id="A">
<image src="/pages/img/1-s-NEW.png"></image>
<text>新品推荐</text>
</view>
</view>
</view>

js

1
2
3
4
5
6
7
8
9
tap_fn:function(e){
console.log(1111111111, e.currentTarget.dataset.id)
var scrollTopId = e.currentTarget.dataset.id;
//scrollTopId我要传的参数
//新建自定义事件,把参数放里
this.triggerEvent('myevent', scrollTopId)

//myevent自定义名称事件,父组件中使用
},

父组件接收参数

navbox 是我的父组件名
myevent 我的事件名
scrollTopId 我随意起的函数名称

html

1
2
<navbox bind:myevent="scrollTopId">
</navbox>

js

e里面有我的参数

1
2
3
scrollTopId:function(e){
console.log(e);
},

API

小程序提供的API按照功能主要分为几大类

网络、媒体、文件、数据缓存、位置、设备、界面、界面节点信息还有一些特殊的开放接口

为了让开发者可以很方便的调起微信提供的能力,例如获取用户信息、微信支付等等,小程序提供了很多 API 给开发者去使用。

要获取用户的地理位置时,只需要:

1
2
3
4
5
6
7
wx.getLocation({
type: 'wgs84',
success: (res) => {
var latitude = res.latitude // 纬度
var longitude = res.longitude // 经度
}
})

调用微信扫一扫能力,只需要:

1
2
3
4
5
wx.scanCode({
success: (res) => {
console.log(res)
}
})

更多api功能参考官方文档

https://developers.weixin.qq.com/miniprogram/dev/api/

API一般调用的约定:

1
2
3
4
5
wx.on* 开头的 API 是监听某个事件发生的API接口,接受一个 Callback 函数作为参数。当该事件触发时,会调用 Callback 函数。
如未特殊约定,多数 API 接口为异步接口 ,都接受一个Object作为参数。
API的Object参数一般由success、fail、complete三个回调来接收接口调用结果,示例代码如代码清单3-17所示,详细说明如表3-9所示。
wx.get* 开头的API是获取宿主环境数据的接口。
wx.set* 开头的API是写入数据到宿主环境的接口。

wx.request

通过wx.request发起网络请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
wx.request({
url: 'test.php',
data: {},
header: { 'content-type': 'application/json' },
success: function(res) {
// 收到https服务成功后返回
console.log(res.data)
},
fail: function() {
// 发生网络错误等情况触发
},
complete: function() {
// 成功或者失败后触发
}
})

代表3-9 API接口回调说明

参数名字 类型 必填 描述
success Function 否 接口调用成功的回调函数
fail Function 否 接口调用失败的回调函数
complete Function 否 接口调用结束的回调函数(调用成功、失败都会执行)

事件

常见的事件类型

1
2
3
4
5
6
7
8
9
10
11
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 动画完成时触发

简单事件代码演示

1
2
3
4
5
6
7
8
9
<!-- page.wxml -->
<view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view>

// page.js
Page({
tapName: function(event) {
console.log(event)
}
})

事件对象属性

1
2
3
4
5
6
7
type	String	事件类型
timeStamp Integer 页面打开到触发事件所经过的毫秒数
target Object 触发事件的组件的一些属性值集合
currentTarget Object 当前组件的一些属性值集合
detail Object 额外的信息
touches Array 触摸事件,当前停留在屏幕中的触摸点信息的数组
changedTouches Array 触摸事件,当前变化的触摸点信息的数组

事件对象实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- page.wxml -->
<view id="outer" catchtap="handleTap">
<view id="inner">点击我</view>
</view>
// page.js
Page({
handleTap: function(evt) {
// 当点击inner节点时
// evt.target 是inner view组件
// evt.currentTarget 是绑定了handleTap的outer view组件
// evt.type == “tap”
// evt.timeStamp == 1542
// evt.detail == {x: 270, y: 63}
// evt.touches == [{identifier: 0, pageX: 270, pageY: 63, clientX: 270, clientY: 63}]
// evt.changedTouches == [{identifier: 0, pageX: 270, pageY: 63, clientX: 270, clientY: 63}]
}
})

target和currentTarget事件对象属性

属性 类型 说明
id String 当前组件的id
tagName String 当前组件的类型
dataset Object 当前组件上由data-开头的自定义属性组成的集合

属性 类型 说明
identifier Number 触摸点的标识符
pageX, pageY Number 距离文档左上角的距离,文档的左上角为原点 ,横向为X轴,纵向为Y轴
clientX, clientY Number 距离页面可显示区域(屏幕除去导航条)左上角距离,横向为X轴,纵向为Y轴

事件绑定与冒泡捕获

事件绑定的写法和组件属性一致,以key=”value”的形式,其中:

key以bind或者catch开头,然后跟上事件的类型,如bindtap、catchtouchstart。自基础库版本1.5.0起,bind和catch后可以紧跟一个冒号,其含义不变,如bind:tap、catch:touchstart。同时bind和catch前还可以加上capture-来表示捕获阶段。
value是一个字符串,需要在对应的页面Page构造器中定义同名的函数,否则触发事件时在控制台会有报错信息。
bind和capture-bind的含义分别代表事件的冒泡阶段和捕获阶段

capture-bind 事件捕获
bind 事件冒泡
capture-catch 将中断捕获阶段和取消冒泡阶段

点击 inner view 会先后调用handleTap2、handleTap4、handleTap3、handleTap1。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<view
id="outer"
bind:touchstart="handleTap1"
capture-bind:touchstart="handleTap2"
>
outer view
<view
id="inner"
bind:touchstart="handleTap3"
capture-bind:touchstart="handleTap4"
>
inner view
</view>
</view>

bind和catch

bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止冒泡事件向上冒泡。如果将上面代码中的第一个capture-bind改为capture-catch,将只触发handleTap2(capture-catch将中断捕获阶段和取消冒泡阶段)

滑动事件

用的就是
touchstart 手指触摸动作开始
touchmove 手指触摸后移动
touchcancel 手指触摸动作被打断,如来电提醒,弹窗

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
bindtouchstart="scrollTouchstart" bindtouchmove="scrollTouchmove" bindtouchend="scrollTouchend"


js
// pages/about/about.js

Page({
data: {
scrollindex: 0, //当前页面的索引值
totalnum: 5, //总共页面数
starty: 0, //开始的位置x
endy: 0, //结束的位置y
critical: 100, //触发翻页的临界值
margintop: 0, //滑动下拉距离
},
onLoad: function () {
},
scrollTouchstart: function (e) {
console.log('滚动到顶部');
console.log(e.touches[0].pageY);
let py = e.touches[0].pageY;
this.setData({
starty: py
})
},
scrollTouchmove: function (e) {
console.log('滚动中');
// console.log(e.touches[0].pageY);
let py = e.touches[0].pageY;
let d = this.data;
this.setData({
endy: py,
})
// 滑动屏幕100px内时,前端给动效(设置margin-top)
if (py - d.starty < 100 && py - d.starty > -100) {
this.setData({
margintop: py - d.starty
})
}
},
scrollTouchend: function (e) {
console.log('滚动到底部');
let d = this.data;
if (d.endy - d.starty > 100 && d.scrollindex > 0) {
this.setData({
scrollindex: d.scrollindex - 1
})
} else if (d.endy - d.starty < -100 && d.scrollindex < this.data.totalnum - 1) {
this.setData({
scrollindex: d.scrollindex + 1
})
}
this.setData({
starty: 0,
endy: 0,
margintop: 0
})
},
})

自定义属性,事件中获取

设置自定义属性
取值自定义属性

1
2
3
4
5
6
7
<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
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//小程序内使用event来传值只能在本页面,到别的页面接收的是空的,所以先传到js在通过url传值
A页面:WXML
<button bindtap="GoHome" open-type="launchApp" data-index="123">进入餐厅</button>

A页面:js page内即可

GoHome: function (e) {
wx.navigateTo({
url: "../HomePage/HomePage?UName=" + e.target.dataset.index,
})
}

B页面:js data内先声明一个参数,用以接收值

data: {
UName:''
},

onload内写,自动获取

onLoad: function (options) {
this.setData({
UName: options.UName
})
console.log(this.data.UName)
},


小程序的组件和api和事件
http://www.dwyblog.cn/2022/02/11/小程序的组件和api/
作者
幸福来敲门
发布于
2022年2月11日
许可协议