# 事件

事件将用户在渲染层的操作,反馈到逻辑层,触发对应的事件处理函数,进而响应用户的交互。事件对象可以传递额外的数据,如 id, dataset, touches。

# 事件使用示例

  • 在组件中绑定一个事件处理函数,如bindtap="handleTap"
<view id="testView" data-hi="QuickApp" bindtap="handleTap">点击</view>
1
  • 在相应的 Page 定义中编写事件处理函数,参数是事件对象 event。
Page({
  handleTap: function(event) {
    console.log(event)
  }
})
1
2
3
4
5
  • 打印的 event 结构如下:
{
  "type": "tap",
  "timeStamp": 868,
  "target": {
    "id": "testView",
    "dataset": {
      "hi": "QuickApp"
    }
  },
  "currentTarget": {
    "id": "testView",
    "dataset": {
      "hi": "QuickApp"
    }
  },
  "detail": {
    "x": 59,
    "y": 36
  },
  "touches": [
    {
      "identifier": 0,
      "pageX": 59,
      "pageY": 36,
      "clientX": 59,
      "clientY": 36
    }
  ],
  "changedTouches": [
    {
      "identifier": 0,
      "pageX": 59,
      "pageY": 36,
      "clientX": 59,
      "clientY": 36
    }
  ]
}
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

# 使用 QJS 函数响应事件

使用 QJS 函数处理事件这种情况下,QJS 函数接受 2 个参数,第一个是 event 对象,event 除了有上面基本的属性外,还具有一个 instance 属性;第二个参数是 ownerInstance,和event.instance 一样是一个 ComponentDescriptor 对象。

代码示例:

  • 在 qxml 中绑定 QJS 函数。
<qjs module="qjs" src="./test.qjs"></qjs>
<view id="testView" data-hi="QuickApp" bindtap="{{qjs.handleTap}}"> Click Button </view>
1
2

注意:绑定的 QJS 函数必须用{{}}括起来

  • test.qjs 文件实现 handleTap 函数
function handleTap(event, ownerInstance) {
  console.log('tap button', JSON.stringify(event))
}
module.exports = {
  handleTap: handleTap
}
1
2
3
4
5
6

ComponentDescriptor 对象拥有一些方法,可以设置组件的样式等。 更多详情请参考文档

# 事件详解

# 事件分类

快应用渲染层中事件分为冒泡事件和非冒泡事件:

  1. 冒泡事件是指当一个组件上的事件被触发后,该事件会向父节点传递。
  2. 非冒泡事件是指当一个组件上的事件被触发后,该事件不会向父节点传递。

冒泡事件列表:

类型 触发条件
touchstart 手指触摸动作开始
touchmove 手指触摸后移动
touchcancel 手指触摸动作被打断,如来电提醒,弹窗
touchend 手指触摸动作结束
tap 手指触摸后马上离开
longpress 手指触摸后,超过 350ms 再离开,如果指定了事件回调函数并触发了这个事件,tap 事件将不被触发
longtap 手指触摸后,超过 350ms 再离开(推荐使用 longpress 事件代替)
transitionend 会在 transition 或 qa.createAnimation 动画结束后触发
animationstart 会在一个 animation 动画开始时触发
animationiteration 会在一个 animation 一次迭代结束时触发
animationend 会在一个 animation 动画完成时触发

注:其他事件如无特殊声明都是非冒泡事件,如 formsubmit事件,inputinput事件,scroll-viewscroll事件

# 事件绑定和冒泡

事件绑定的写法和组件的属性相同。

  • key 以bindcatch开头,后面拼接事件的类型,如bindtapcatchtouchstartbindcatch后也可以紧跟一个冒号,如bind:tapcatch:touchstart,作用一致。
  • value 是一个字符串,需要在对应的 Page 中定义同名的函数。否则当触发事件的时候会报错。
  • bind 与 catch 的区别:bind 事件绑定不会阻止冒泡事件向上冒泡,而 catch 则会。

代码示例:

<view id="view1" bindtap="handleTap1">
  view1
  <view id="view2" catchtap="handleTap2">
    view2
    <view id="view3" bindtap="handleTap3">
      view3
    </view>
  </view>
</view>
1
2
3
4
5
6
7
8
9

执行效果:

  • 点击 view3 会先后调用handleTap3handleTap2(这是因为 tap 事件会冒泡到 view2,而 view2 阻止了 tap 事件冒泡,不再向父节点 view1 传递)
  • 点击 view2 只触发handleTap2
  • 点击 view1 只触发handleTap1

# 事件的捕获阶段

捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段相反。捕获阶段监听事件,可以采用capture-bindcapture-catch关键字,后者将中断捕获阶段和取消冒泡阶段。

示例代码:

<view id="view1" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2">
  view1
  <view id="view3" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
    view3
  </view>
</view>
1
2
3
4
5
6

执行效果:

  • 点击 view3 会先后调用handleTap2handleTap4handleTap3handleTap1

示例代码:(上面代码中的第一个capture-bind改为capture-catch)

<view id="view1" bind:touchstart="handleTap1" capture-catch:touchstart="handleTap2">
  view1
  <view id="view3" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
    view3
  </view>
</view>
1
2
3
4
5
6

执行效果:

  • 点击 view3 只触发handleTap2

# 事件对象

当组件触发事件时,逻辑层绑定的处理函数会收到一个事件对象。

属性 类型 说明
type String 事件类型
timeStamp Integer 事件生成时的时间戳
target Object 触发事件的组件的属性值集合
currentTarget Object 当前组件的属性值集合
detail Object 自定义事件对象额外的信息
touches Array 触摸事件,当前停留在屏幕中的触摸点信息的数组
changedTouches Array 触摸事件,当前变化的触摸点信息的数组

各属性详细信息如下。

# target

触发事件的源组件。

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

# currentTarget

事件绑定的当前组件。

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

说明: target 和 currentTarget 可以参考上例中,点击 view3 时,handleTap3 收到的事件对象 target 和 currentTarget 都是 view3,而 handleTap2 收到的事件对象 target 就是 view3,currentTarget 就是 view2。

# dataset

在组件节点中可以定义一些自定义数据,触发事件时会传入回调中处理。

在 QXML 中,这些自定义数据以 data- 开头,多个单词由连字符 - 连接。这种写法中,连字符写法会转换成驼峰写法,而大写字符会自动转成小写字符。如:

  • data-custom-value ,最终会呈现为 event.currentTarget.dataset.customValue
  • data-customValue ,最终会呈现为 event.currentTarget.dataset.customvalue

# touches

touches 是一个数组,每个元素为一个 Touch 对象。 表示当前停留在屏幕上的触摸点。另外 canvas 触摸事件中携带的 touches 是 CanvasTouch 数组。

# Touch 对象

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

# CanvasTouch 对象

属性 类型 说明
identifier Number 触摸点的标识符
x, y Number 距离 Canvas 左上角的距离,Canvas 的左上角为原点 ,横向为 X 轴,纵向为 Y 轴

# changedTouches

changedTouches 数据格式同 touches。 表示有变化的触摸点,如从无变有(touchstart),位置变化(touchmove),从有变无(touchend、touchcancel)。

# detail

自定义事件数据,详见组件定义中各个事件的定义。

点击事件的detail 带有的 x, y 同 pageX, pageY 代表距离文档左上角的距离。

在线客服