## QJS 响应事件

普通函数响应事件，需要经过逻辑层和渲染层的通信，有一定的耗时，在某些情形下会导致交互延迟。如果利用 QJS 函数响应事件，让开发者的代码运行在渲染层，则可以省去通信，使交互更顺畅。

### ComponentDescriptor

QJS函数除了纯逻辑的运算，还可以通过封装好的`ComponentDescriptor` 实例来访问以及设置组件的样式。

代码示例：

```js
var qjsFunction = function(event, ownerInstance) {
  var instance = ownerInstance.selectComponent('.red') // 返回组件的实例
  instance.setStyle({
    'font-size': '16px'
  })
  instance.getDataset()
  instance.setClass(className)
  return false
}
```

其中入参 `event` 是快应用[事件对象](./event.html)，在基础属性上多了 `event.instance` 来表示触发事件的组件的 `ComponentDescriptor` 实例。`ownerInstance` 表示的是触发事件的组件所在的组件的 `ComponentDescriptor` 实例，如果触发事件的组件是在页面内的，则 `ownerInstance` 表示页面实例。

`ComponentDescriptor`实例包含的方法如下：

| 方法 | 参数 | 描述 |
| --- | --- | --- |
| selectComponent | selector 对象 | 返回组件的 `ComponentDescriptor` 实例。 |
| selectAllComponents | selector 对象数组 | 返回组件的 `ComponentDescriptor` 实例数组。 |
| setStyle | Object/string | 设置组件样式，支持`rpx`。设置的样式优先级比组件 qxml 里面定义的样式高。不能设置最顶层页面的样式。 |
| addClass/removeClass/ hasClass | string | 设置组件的 class。设置的 class 优先级比组件 qxml 里面定义的 class 高。不能设置最顶层页面的 class。 |
| getDataset | 无 | 返回当前组件/页面的 dataset 对象 |
| callMethod | (funcName:string, args:object) | 调用当前组件/页面在逻辑层定义的函数。funcName 表示函数名称，args 表示函数的参数。 |
| getState | 无 | 返回一个 object 对象，当有局部变量需要存储起来后续使用的时候用这个方法。 |
| triggerEvent | (eventName, detail) | 和组件的[triggerEvent](./../custom-component/events.html)一致。 |

QJS 运行在渲染层，需要有一个机制和逻辑层通信，上面的 `callMethod` 可以允许开发者在 QJS 里面调用逻辑层的方法。

### 使用示例

- QXML 定义事件：

```html
<qjs module="test" src="./test.qjs"></qjs>
<view
  change:prop="{{test.propObserver}}"
  prop="{{propValue}}"
  bindtouchmove="{{test.handleTouchMove}}"
  class="movable"
></view>
```

上面的`change:prop`（属性前面带 change:前缀）是在 prop 属性被设置的时候触发 QJS 函数，值必须用`{{}}`括起来。类似 Component 定义的 properties 里面的 observer 属性，在 `setData({propValue: newValue})` 调用之后会触发。

**注意**：QJS 函数绑定必须放到 `{{}}` 里。当 prop 的值被设置时， QJS 函数就会触发，即使值没有发生改变。

- QJS 文件 `test.qjs` 里面定义并导出对应函数：

```js
module.exports = {
  handleTouchMove: function(event, instance) {
    console.log('handleTouchMove', JSON.stringify(event))
  },
  propObserver: function(newValue, oldValue, ownerInstance, instance) {
    console.log('propObserver', newValue, oldValue)
  }
}
```
