微信小程序:事件浅晰

关于小程序的事件,我们知道的是,在组件上面绑定对应的响应事件,用户在这个组件上操作就会触发预先绑定的事件,执行我们想要执行的代码。

比如:



    
        outer view
        
            middle0 view
        
        
            middle1 view
            
                inner view
            
        
    


// pages/demo_0/index.js
Page({

  onOuter: function () {
    console.log('onOuter')
  },

  onMiddle0: function () {
    console.log('onMiddle0')
  },

  onMiddle1: function () {
    console.log('onMiddle1')
  },

  onInner: function () {
    console.log('onInner')
  }
})
/* pages/demo_0/index.wxss */

.outer {
    background-color: red;
    width: 750rpx;
    height:750rpx;
    color: white;
}

.outer .middle-0 {
    background-color: blue;
    width: 350rpx;
    height: 350rpx;
}

.outer .middle-1 {
    background-color: pink;
    width: 350rpx;
    height: 350rpx;

}

.outer .middle-1 .inner {
    background-color: black;
    width: 200rpx;
    height: 200rpx;
}
image.png

当点击 黑色的 inner 的时候,就会触发 onInner。(当然,由于tap是冒泡事件,同时也会触发 onMiddle1onOuter

对应的log

onInner
onMiddle1
 onOuter

那么这一切是怎么发生的呢?
当用户点击黑色的 inner 的时候,系统会根据点击的点的坐标来确定被点击的组件是哪一个。

事件定位

每一个页面都有一个组件树,在上面的例子中,我们的组件树结构如下:


image.png

点击事件发生时,系统会根据这个组件树,从树的最顶端开始往下来寻找被点击的点在哪个组件上。以上面的代码为例:

  1. 系统首先确认,点击的点在page
  2. 确认点在container
  3. 确认点在outer
  4. 接下来判断点击的点没有在middle-0
  5. 判断middle-0的兄弟组件middle-1,发现这个点在middle-1
  6. 最后系统会继续遍历期子组件inner,这个点也在inner的区域内

因为inner没有兄弟组件和子组件,所以遍历过程结束。结果是,用户点击了inner,这里我们借鉴iOS的概念,称inner为这次tap事件的第一响应者。(如果这时候点击的是middle-1上的非inner区域,那么遍历到middle-1后,会再测试inner,发现点击的点没有在inner上,从而确定用户点击了middle-1上的非inner区域。)

事件响应

上面的过程就是系统的事件的定位过程。在定位到被点击的组件之后,接下来就是事件响应了。

在解释事件响应前,首先要清楚一个概念:事件类型

在小程序中,事件类型主要有:(摘自小程序官方文档)

类型 触发条件 最低版本
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 设备,重按时会触发

当然还有其它的特殊事件,仅存在于特定的组件,比如submit事件,或者scroll事件。

当组件上产生了tap事件,我们也指定了tap对应的响应函数时,对应的函数就会被调用。其它事件同理。

前面我们提到,点击 inner 的时候,同时也触发了onMiddle1onOuter,我们再来增加一个知识:冒泡事件。

冒泡事件

冒泡事件是指,事件由第一个响应的组件响应之后,会再往上一级组件传递。也就是说,inner 响应了 tap事件执行了onInner之后,还会将tap事件继续往它的父组件传递。于是就出现了刚刚实验的情况,点击了inner后,发现middle-1outer的tap响应函数也执行了。

如果不希望事件冒泡,可以使用catch对事件进行捕捉,只需要把bind替换成catch即可:



    
        outer view
        
            middle0 view
        
        
            middle1 view
            
                inner view
            
        
    

target 和 currentTarget

target为第一响应者,在上例中就是 inner,而currentTarget则为响应函数对应的组件。
我们修改一下代码:




    
        outer view
        
            middle0 view
        
        
            middle1 view
            
                inner view
            
        
    

// pages/demo_0/index.js
Page({

  onOuter: function () {
    console.log('onOuter')
  },

  onMiddle0: function () {
    console.log('onMiddle0')
  },

  onMiddle1: function (options) {
    console.log('************* onMiddle1 ****************')
    console.log(options)
    console.log('************* onMiddle1 ****************')
  },

  onInner: function (options) {
    console.log('************* inner ****************')
    console.log(options)
    console.log('************* inner ****************')
  }
})

点击inner后,log为:


image.png

根据我们上面的定义,在onInner中,target和currentTarget都是inner,而在onMiddle1中,target是inner而currentTarget则是middle-1
同时也可以看到,冒泡的过程,onInner先于onMiddle1执行,最后执行onOuter

这就是今天要分享的内容,如有不足和错误欢迎讨论。

更多信息,参见微信官方文档

你可能感兴趣的:(微信小程序:事件浅晰)