微信小程序事件绑定
一 通过实例来认识
(一) 给出代码
我们直接通过一个实例来引入我们想要讲解的内容:
<input type="text" bindinput="handleInput" />
<button bindtap="handletap" data-operation="{{1}}">+</button>
<button bindtap="handletap" data-operation="{{-1}}">-</button>
<view>你输入的是:{{number}}</view>
上述代码就四行,首先是一个 input 输入框,目的是用来输入一些值,同时下面标签就会显示,接着是两个 button 用来分别执行 +1 或者 -1 的操作,最后一个 view 标签就是为了 进行数据输入或变化的回显
Page({
  data: {
    number:0
  },
  handleInput(e){
    this.setData({
      number:e.detail.value
    })
  },
  handletap(e){
    const operation = e.currentTarget.dataset.operation
    this.setData({
      number:this.data.number + operation
      // number:this.data.number * 1 + e.currentTarget.dataset.operation
    })
  }
})
这里给出的就是对应的 js 代码,涉及到了对于输入以及 +1 或者 -1 操作的一个具体逻辑处理,核心就是围绕 data 中定义的 number 变量进行处理(具体逻辑接着会提到),结合前面的 wxml 代码分析一下:
(二) 分析代码
分析标签中属性中的部分:
bindinput="handleInput"
bindtap="handletap" data-operation="{{-1}}"
- 绑定事件的关键字是 bind例如上面用到的bindinput和bindtap就是分别对于输入和点击事件的一个绑定
- 而后面的一个名称例如 handleInput 就是自定义的事件名称,我们在 js 中书写方法也是与这个后面的名称相对应
- 注:绑定关键字为 bind 仅针对此例,并非只是 bind
补充几个 input 中相对常用的事件绑定属性
| 属性 | 类型 | 必填 | 说明 | 最低版本 | 
|---|---|---|---|---|
| bindinput | eventhandle | 是 | 键盘输入时触发,event.detail = {value, cursor, keyCode},keyCode 为键值,2.1.0 起支持,处理函数可以直接 return 一个字符串,将替换输入框的内容。 | 1.0.0 | 
| bindfocus | eventhandle | 是 | 输入框聚焦时触发,event.detail = { value, height },height 为键盘高度,在基础库 1.9.90 起支持 | 1.0.0 | 
| bindblur | eventhandle | 是 | 输入框失去焦点时触发,event.detail = {value: value} | 
如果想要获取到输入框的值,通过时间源对象来获取 e.detail.value
(1) JS 中赋值问题
输入框中输入的值赋值给 data 中的 number,如果按惯性思维直接赋值是有问题的
- 
不能使用 this.data.numer = e.detail.value 
- 
不能使用 this.number = e.detail.value 
- 
需要使用: 
this.setData({
	number:e.detail.value
})
(2) JS 中按钮传参问题
添加按钮点击事件:关键字是 bindtap
我们按钮想要达到的目的是,点击按钮进行 number 的 +1 或者 -1 ,通过根据我们上面的 js 代码可以看出,这里所采用实现的方式是根据页面属性中传来的参数,进行相加,例如 number + 1 或者 number + (-1) 达到加减效果
但是,直接传参是有问题的!!!只能通过属性赋值
正解:bindtap="handletap" data-operation="{{-1}}"
(3) 忘记想要的值对应在哪里
说明:如果记不住例如:e.detail.value、e.currentTarget.dataset.operation 则可以使用如下的方式,先把事件打印出来
handleInput(e){
    console.log(e);
},
在找到对应的层级
二 事件绑定类别
(一) 分类
我们上面的例子使用了 bind 这个事件绑定关键字,但是它会发生冒泡事件
- 
冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递 
- 
非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递 
我们还有一些别的选择,我们下面在 (3) (4) 中会一个一个进行分析
- bind:普通绑定(会发生冒泡事件)
- catch:可以阻止事件冒泡
- capture-bind: 捕获阶段绑定(后面的捕获流程和冒泡流程还会继续执行)
- capture-catch:中断捕获阶段和取消冒泡阶段,在捕获阶段阻止事件的传递
(二) 冒泡事件列表
在分析前,我们还要补充一个点,那就是 WXML 的冒泡事件列表:
我们起码现在知道了 bind 和 catch 的作用,但是正例如我们上面用到的 bindinput 或者 bindtap ,bind 后面的内容又是什么呢?是固定的还是自定义的呢?这一段我直接贴一段官网的文档说明
| 类型 | 触发条件 | 最低版本 | 
|---|---|---|
| touchstart | 手指触摸动作开始 | |
| touchmove | 手指触摸后移动 | |
| touchcancel | 手指触摸动作被打断,如来电提醒,弹窗 | |
| touchend | 手指触摸动作结束 | |
| tap | 手指触摸后马上离开 | |
| longpress | 手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发 | 1.5.0 | 
| longtap | 手指触摸后,超过350ms再离开(推荐使用longpress事件代替) | |
| transitionend | 会在 WXSS transition 或 wx.createAnimation 动画结束后触发 | |
| animationstart | 会在一个 WXSS animation 动画开始时触发 | |
| animationiteration | 会在一个 WXSS animation 一次迭代结束时触发 | |
| animationend | 会在一个 WXSS animation 动画完成时触发 | |
| touchforcechange | 在支持 3D Touch 的 iPhone 设备,重按时会触发 | 1.9.90 | 
注:除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如 form 的submit事件,input 的input事件,scroll-view 的scroll事件,(详见各个组件)
看完上面的表格,应该就比较清楚了,正因为我们很多事件都是通过手机点一下某个组件等进行,所以 tap 是比较常用的
(三) bind 和 catch
说明:代码在下面自取
(1) bind
前面我们提到了,使用 bind 会发生冒泡事件,我们来模拟一下
首先我们写了三个嵌套的 view 标签,然后接着使用 bindtap 进行事件绑定,进行一个基本的打印逻辑,看看会有什么情况发生
当点击中间层后,首先执行了中间层的事件效果,但是最外层的事件效果也被执行了,这也就是冒泡事件发生了
冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递
非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递
(3) catch
这一次我们仍然点击中间这一层,如果在上面的基础上,我们将中间层的事件绑定使用 catch,而不是 bind ,结果会是怎样呢?
结果就是冒泡事件被阻止了,点击后只显示中间层的事件
(四) capture-bind 和 capture-catch
前面提及到这两个内容的时候,我们提到了一个概念也就是事件的捕获阶段,简单说一下:
自基础库版本 1.5.0 起,触摸类事件支持捕获阶段。捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段恰好相反。需要在捕获阶段监听事件时,可以采用capture-bind、capture-catch关键字,后者将中断捕获阶段和取消冒泡阶段。
(1) capture-bind:tap
依旧是刚才的例子,将三层的属性都修改为 capture-bind:tap="handleTap1" 这种形式的
当我们点击最里层的内容时,执行结果如下:
即它与包裹它的两层都执行了,且是从外至内
(2) capture-catch:tap
将三层属性修改为 capture-catch:tap="handleTap1" 这种形式,点击任意一层:
结果都是只执行最外层的
(五) 简单总结
- bind:点击会触发它和包裹它的所有事件,且从内向外执行(冒泡事件)
- catch:点击哪个就触发哪个,独立的(阻止冒泡事件)
- capture-bind: 点击会触发它和包裹它的所有事件,且从外向内执行
- capture-catch:如何点击都只会触发最外层的事件
(六) 代码提取
代码给出的是 capture-bind:tap 的情况, bindtap 或者 catchtap 以及 capture-catch 只需要将 capture-bind:tap 替换就行了
wxml
<view class="outer" capture-bind:tap="handleTap1">
  这是最外层
  <view class="middle" capture-bind:tap="handleTap2">
    这是中间层
    <view class="inner" capture-bind:tap="handleTap3">
      这是最里层
    </view>
  </view>
</view>
wxss
.outer {
    text-align: center;
    background-color: red;
    height: 300rpx;
}
.middle {
    background-color: orange;
    width: 60%;
    height: 200rpx;
}
.inner {
    background-color: yellow;
    width: 60%;
    height: 100rpx;
} 
                    
                
 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号