一、三大API了解一下
1、事件监听API
学过JavaScript的会知道,除了addEventListener可以监听事件,还有一个on开头的API可以监听事件,只需要on+“事件名称”,例如:
//一个按钮的点击事件
button.onclick = function(){
......
}
那么微信小程序开发也差不多,区别就是不是on,是bind:1、【bind+事件名称="js里写的函数名"】 2、【bind:事件名称="js里写的函数"】
2、同步API
特点1:以Sync结尾的API都是同步API
特点2:同步API的结果可以通过函数return获得,执行错误会抛出异常
3、异步API
特点:类似jQuery种的$.ajax{options}函数,需要通过success、fail、complete接受调用结果
二、数据绑定:就是能在WXML里用JS的成员
数据绑定原则:1、在js文件的data里定义数据
2、在WXML里使用数据
1、在js文件data里定义数据
每个页面的js文件都要有一个Page()函数,作为这个页面的入口,当调用Page()函数就能开始进入这个页面的文件,Page()里面要传一个【对象参数】:Page( { 对象 } ),那么这个对象里就包含一个对象成员:data,写法跟JavaScript、axios、vue这些语言写对象的语法一样的,模板:
Pages({
data: {
定义的数据1:xxx,
定义的数据2:xxx,
......
},
......
})
例子:
Page({
data: {
p: "js里的data"
}
})
2、在WXML里引用这些数据
学过vue对这个不会陌生,又是Mustache语法,也就是“双花括号”:{{ }},模板:
<view>{{ 要绑定的数据变量名字 }}</view>
例子:
<view>{{ p }}</view>
3、标签的属性也可以动态绑定数据
例子:
<image src="{{ src }}" mode=""/>
Page({
data: {
src: "../img/树.jpg"
}
})
4、另外,{{ }}里还可以做算术运算,这里不做演示了,反正就是能算数就行了
三、事件
1、有哪些事件?怎么在WXML绑定?
一般来说就这几个常用的,截一下黑马的图简单看看
在WXML里写的方式很简单,就【bind+事件="js里写的函数名"】,或者【bind:事件="js里写的函数名"】
2、在JS里怎么写对应绑定事件的函数
然后接着就是再JS文件里写对应名字的函数就行了,也很简单,这些函数都是跟data同级的,在data后面写个逗号“,”,然后接着写函数就行了:
3、事件对象
跟JavaScript一样,每个事件的触发都会产生一个对应的【事件对象】——>【event】,下面是它的一些属性详情:
我知道以各位的智商肯定看不懂也不想看,那么下面我将结合案例给大伙看看这些属性到底是啥:
(1)tap事件
例子1:设置一个按钮,点一下就在控制台输出这个“点击”事件对象
<!-- WXML部分 -->
<view id="father" bind:tap="showE">
<!-- 注意!!我是给view这个父盒子绑定的tap事件,而不是给按钮button!! -->
<button type="primary" id="son">点一下返回一个当前事件信息</button>
</view>
//WXSS部分
view{
padding-top: 30px;
height: 100px;
background-color: burlywood;
}
这里js里如果要输出事件对象,就给函数传入【事件对象参数】就行了,在JavaScript里教过,事件对象要么叫event、要么叫e,看自己喜欢任选一个传进去就行
//JS部分
Page({
data: {
//数据信息
},
showE(e){
console.log(e)
}
})
这个事件就是点击(tap)事件,现在我点击一下【绿色这个按钮】后输出了事件对象:
我再提示一下,我是给【view】绑定的【tap事件】,【button】啥也没有;但是我点击的时候点的是【button】,而不是点【view】。(view的id是father,button的id是son)所以会看到currentTarget指向father,target指向son;
可是为什么点了button也会触发事件?为什么又会涉及到view?因为button不也是包在view里面吗?点击button不也算是点view嘛。然后学过JavaScript的会知道【冒泡机制】,点击子元素的时候,触发的事件会往外冒泡,牵连到它的父容器元素也触发该事件,所以会牵连到view
(2)input事件和change事件
例子2:现在再演示一下input事件和change事件
<!-- WXML部分 -->
<input bindinput="inputContent" value="bind:input"/>
<input bind:change="changeContent" value="bind:change"/>
//WXSS部分
input{
width: 55%;
border:1px solid black;
margin-top: 30px;
margin-left: 70px;
}
Page({
data: {
//数据信息
},
inputContent(e){
console.log(e)
},
changeContent(e){
console.log(e)
}
})
那么input事件就是你只要写了东西,或者删除了东西,文本框有一点变化都会触发它,这里我只是删了几个字就打出来一堆事件对象
而change事件就是不管你写了什么、删了什么,只有当你摁下【enter】键之后才会触发
那么怎么获取input输入的值?
【e.detail.value】就可以获得了
Page({
data: {
//数据信息
},
inputContent(e){
console.log(e.datail.value)
}
})
四、动态改变data的数据
这里跟JavaScript学的有所不同,以前我们学JavaScript时改变数据不就直接【this.数据 加减乘除】吗,但是这里要调用到一个函数:【this.setData()】
但是在this.setData()函数外面,我们还是可以用【this.data.数据】这样来做一些运算操作,但是不管外面【this.data.数据】怎么变了,最后还是得依靠【this.setData()】来给它设置新的值。还有,在【this.setData()】里this的指向会变,如果实在要用this,最好在外面用个变量存下this,在用这个变量(像const that = this, that.data.xxx......这样)
第一步:在JS里与data同级的地方写对应某个事件绑定的函数,然后在里面调用【this.setData()】
第二步:在【this.setData()】里传入一个对象参数:【{ ...... }】
第三步:在{ ...... }对象里不能直接对数据加减乘除,要按照data对象的写法那样,【数据: this.data.数据(加减乘除)】,相当于重新定义一个新的对象并获得新的值,然后再将这个对象值给回并覆盖原本data对象的值
例子:点击按钮下面数据就增加
<!-- WXML部分 -->
<view>
<button type="primary" bind:tap="changeData">点一下返回一个当前事件信息</button>
<text>{{ count }}</text>
</view>
//WXCC部分
view{
padding-top: 30px;
height: 100px;
background-color: burlywood;
}
text{
font-size: 27px;
margin-left: 140px;
background-color: darkorange;
}
//JS部分
Page({
data: {
//数据信息
count: 0
},
//tap事件绑定的函数
changeData(){
//this.setData()函数改值
this.setData({
//按照对象的写法
count: this.data.count + 1
})
}
})
那么这里有一个问题,我在学到后面做实例的时候发现的一个问题:
我想做一个轮播图,这里的图片是来自一个“随机生成图片”的网络API接口,那么要让轮播图有多张图片,当然就是利用【wx:for】(下面会讲到)指令来遍历一个数组,那就需要一个数组来获取这个“随机生成图片”的网络API接口传回来的图片url链接,但是this.setDate()函数我发现这个bug导致我很头疼,看一下下面这个图片就知道了
后面研究了半天终于得到一个方法动态改变data的数组的值:
1、在wx.request( )函数里发送完请求,然后再wx.request( )里、this.setData( )外,用一个变量先获取到【传回来的数据值】
getImg(){
wx.request({
url: 'https://qqlykm.cn/api/free/random/get',
method: 'get',
data: {
key: '0usuKOMipmKqjBXis3l1hD6PZK'
},
success: (res) => {
//在这我定义一个新数组list,用来代替data的img数组,也就是原数组
let list = this.data.img
//然后用【数组.push()】的方法给数组后面添加元素
list.push(res.data.data.img)
this.setData({
//......
})
}
})
}
2、然后,现在这个list“临时数组”已经获取到图片src值了,然后再到this.setData( )函数里真正把值给回data的img[ ]数组,物归原主,达到data的数组改变值的效果
getImg(){
wx.request({
url: 'https://qqlykm.cn/api/free/random/get',
method: 'get',
data: {
key: '0usuKOMipmKqjBXis3l1hD6PZK'
},
success: (res) => {
let list = this.data.img
list.push(res.data.data.img)
this.setData({
//这里才是真正把值给到data的img数组
img: list
})
}
})
}
补充,微信小程序里数组的操作
Array.push() :在数组后面继续插入内容
Array.pop():拿走数组最后一个内容
Array…shift():拿走数组的第一个内容 (unshift也是拿走最后一个)
Array.reverse():对数组从大到小排列
Array.sort():对数组从小到大排列**
Array.splice(起始位置 , 位数,”增添内容”):从数组中取出以起始位置开始的位数的内容,并写入增添内容,可用来删除内容与替换,例如people.aplice(1,2,“name”)
Array.concat():将两个或多个数组合并成一个新数组,并返回新数组
Array.splice():从数组中增删元素,并返回被删除的元素
五、函数传参
1、在WXML里怎么传参?
微信小程序绑定事件的机制有点头疼,因为【bind事件】绑定的是一个函数名字符串,这个一整串字符串就是函数名字,就不能直接传参了,比如下面这样写是错的、电脑看不懂
<button bindtap="show(123)">按钮</button>
//报错!(123)也会被当作函数的名字
那么有个办法:在标签里加上【data-自定义形参名字 = " {{ 实参 }} "】,data-后面接的东西会被解析成传给函数的【形参】," "里的东西会被解析为【实参值】
2、怎么在JS函数里获取到实参?
好,现在你传过去了,怎么获取实参呢?有些人看我前面说:data-后面接的东西会被解析成传给函数的【形参】,然后就直接在JS里这么写,错!!
btbHandler(info){
console.log(info)
}
微信小程序就是这么麻烦......你只能在JS函数里传event事件对象参数,然后再调用【event.target.dataset.参数名】才能获取到实参数值......
例子:(WXSS代码我就免了,跟前面一样的)
<view>
<button type="primary" bind:tap="show" data-num="{{666}}">点一下返回函数参数</button>
<!-- 现在data-后面的【num】会解析为参数名,【666】就是它的值 -->
<text>{{ count }}</text>
</view>
Page({
data: {
//数据信息
count: 0
},
//tap事件绑定的函数
show(e){
console.log(e)
console.log(e.target.dataset.num)
//this.setData()函数改值
this.setData({
count: e.target.dataset.num
})
}
})
六、条件渲染
1、wx:if
可以通过【条件渲染】来根据不同的条件渲染不同的值,你可以在JS部分直接if-else判断设置值,当然也可以用新方法:在WXML里用【wx:if】来条件渲染
【wx:if】【wx:elif】【wx:else】就等于【if(...){...}else if(...){...}else{...}】
例子:
<view wx:if="{{ type === 1 }}">男</view>
<view wx:elif="{{ type === 2 }}">女</view>
<view wx:else>人妖</view>
2、结合<block>使用wx:if
要一次性对多个组件进行【显示】或【隐藏】,可以用一个<block></block>包起来,然后再block上用wx:if来条件判断、控制block的属性(但是注意,block不是一个组件,他只是一个包裹性质的容器,他不会再页面上有任何渲染,不要浪费精力去给block设置样式)
wx:if判断【true】,block就显示;【false】就隐藏
<block wx:if="{{ false }}">
<view> view1 </view>
<view> view2 </view>
</block>
<block wx:if="{{ true }}">
<view> view1 </view>
<view> view2 </view>
</block>
3、补充一下,还可以用hidden属性来【隐藏】、【显示】
这个就不用搭配wx:if了,直接判断{{ }}里面,true就隐藏,false就显示
<view hidden="{{false}}">hidden控制隐藏、显示</view>
那么wx:if和hidden有什么区别?
前面学了wx:if知道,wx:if是根据判断条件来控制这个组件【渲染还是不渲染】,简单说就是符合条件就有这个组件,不符合就移除组件
而hidden的本质是设置样式,true的时候就自动设置display: none,不符合条件就自动设置display: block,控制组件显示、隐藏
4、wx:for遍历数组
给WXML标签设置了【wx:for】就可以遍历数组,{{ }}里写data设置的数组名字,
然后微信小程序自带的index是数组的下标、item是数组的每个成员
例子:
<view wx:for="{{ Arrays1 }}">
<!-- index就是数组的下标,不是自定义的,微信小程序自带的 -->
<!-- item就是遍历的数组每个成员,不是自定义的,微信小程序自带的 -->
{{ index+1 }}、{{ item }}
</view>
Page({
data: {
Arrays1: [1,2,3,4,5]
}
})
当然你要是不喜欢微信小程序自带的index、item名字,你也可以自己改
wx:for-index=" "自定义下标名, wx:for-item=" "自定义成员名
<view wx:for="{{ Arrays2 }}" wx:for-index="i" wx:for-item="name">
<!-- wx:for-index="i"自定义了下标名是i -->
<!-- wx:for-item="name"自定义了成员用name代替 -->
{{ i+1 }}、{{ name }}
</view>
Page({
data: {
Arrays2:['Mike','岑梓铭','Jony J','Curry','你大爷','哇哈哈','我是你爹']
}
})
5、最后补充一下:wx:key
跟数据库一样,微信小程序希望每个列表数据都有主键,以防止出现重复冗余数据
wx:key=""设置主键,里面不需要再{{}}这样写,直接写属性名就行
还有,对象的话就设置id为主键,没有的话直接设置下标index也可以
例子:前面的例子我没有设置wx:key,它就会报警告
那么我都给他们设置index下标为主键就行了
<view wx:for="{{ Arrays1 }}" wx:key="index">
{{ index+1 }}、{{ item }}
</view>
<view wx:for="{{ Arrays2 }}" wx:for-index="i" wx:for-item="name" wx:key="i">
{{ i+1 }}、{{ name }}
</view>
然后这里我设置一个对象数组,里面我设置有一个属性是id,那么我这里就以这个id为主键:
<view wx:for="{{ Arrays3 }}" wx:key="id">
{{ index+1 }}、{{ item.name }}
</view>
Page({
data: {
Arrays3:[{
id:1,
name:'周杰伦'
},
{
id:2,
name:'岑梓铭'
},
{
id:3,
name:'Jony J'
}]
}
})