# 事件

和数据的获取相反的一面就是数据的发送和提交，发送数据需要2个步奏才能完成，本节将讲解第一个步奏——事件

## 什么是事件

从编程的角度来看，事件就是一个会发生影响的操作行为。而进行这样的操作行为的执行者通常情况都会是浏览器的用户。比如鼠标的点击，键盘的操作等。

如果程序想要根据用户的这些操作行为做出反应的话，就需要依次进行以下2个步奏：

1. 绑定事件
2. 当操作触发，执行预先设定的任务

虽然不同用户可以对计算机做出完全不同的行为和操作，但是不管任何操作，都需要通过一些设备来完成。例如鼠标点击，敲击键盘。程序可以监控这些设备，并对设备操作做出反应。

当我们选择设备的其中一种操作模式，并提供一个已设定的操作任务的时候，我们就称之为绑定事件。

例如，在程序刚加载的时候，在没有任何用户操作的情况下，设置当鼠标点击屏幕按钮的时候，就在屏幕中显示一个A。

设定完成之后，如果用户不去点击屏幕的按钮，那么A也永远不会出现。只有当用户通过鼠标，并点击了设定的那个按钮，才会出现A。

在这个例子中，我们把鼠标点击触发称之为绑定事件，把在屏幕显示一个A称之为当操作触发，执行预先设定的任务

## RCRE中的事件绑定

在RCRE中，只有无状态组件才支持事件绑定，container组件本身是不支持绑定事件的。

任何一个无状态组件，都会含有一个`trigger`属性。如果设置了`trigger`属性，那么就等同于会监听这个组件所触发的某个事件。

`trigger`属性值是一个数组，数组中每一个元素都是一个普通对象值。一个对象就代表着一个事件的绑定配置。

如果想给一个组件绑定多个事件，就只需要在`trigger`属性中添加多个事件配置即可。

例如, 加入我们想给一个按钮添加鼠标按钮按下和鼠标按钮松开的事件：

那么就需要在Button组件的trigger属性上，同时添加2个对象。

一个对象的event属性是onMouseDown，一个对象的event属性是onMouseUp。

`event`属性是指当前组件所支持的事件名称，不同的组件会有不同的事件触发名称和机制，请参考组件文档来获取具体的使用场景。

除了event属性之外，还需要一个targetCustomer属性。

targetCustomer的内容将会在下一节专门解析，本节预先将其设置为$this。在这里，我们可以把它理解成当事件触发，它会把params中的数据同步到当前的container组件上。

params指事件触发时候，传递时所带的参数值，在params中，可以使用ExpressionString来从container组件中获取值。

小例子：

```json
{
    "body": [
        {
            "type": "container",
            "model": "buttonZone",
            "data": {
                "mouseStatus": "none"
            },
            "children": [
                {
                    "type": "button",
                    "text": "点个按钮试试看",
                    "trigger": [
                        {
                            "event": "onMouseDown",
                            "targetCustomer": "$this",
                            "params": {
                                "mouseStatus": "down"
                            }
                        },
                        {
                            "event": "onMouseUp",
                            "targetCustomer": "$this",
                            "params": {
                                "mouseStatus": "up"
                            }
                        }
                    ]
                },
                {
                    "type": "text",
                    "text": "mouse status: #ES{$data.mouseStatus}"
                }
            ]
        }
    ]
}
```

上面的这个例子，
两个按钮会自动

当配置中还有`params`的时候，传递给`targetCustomer`所指向的`DataCustomer`不光光是一个通知，还有`params`这个属性所表述的值。

在`params`这个对象中，支持使用Expression String来动态获取当前所属的container中数据模型的值。

### 调试模式
不同组件的触发的事件会带有不同的参数，而且参数值的数据结构也都不相同。

查看这些参数和数据结构最佳的方式就是通过浏览器的开发者工具。

RCRE提供了调试模式，可以在事件触发的时候，将当前事件触发的所有参数都输出到浏览器控制台中。

开启只需在事件定义中添加debug: true。

通过这个工具，可以很轻松的查看`$args`的值。

如：

```_raw_json
{
    "trigger": [{
        "event": "onClick",
        "targetCustomer": "$this",
        "params": {},
        "debug": true
    }]
}
```

### 在某些条件下才会触发
一个组件的一种类型事件，有的时候在不同的状态下也有不同的作用。所以还可以使用`condition`字段来决定是否要执行这个事件。

`condition`的值是一个ExpressionString。当返回值是true的时候，则这个事件将会继续运行，把数据发送到对应的DataCustomer。如果返回false，则不会有任何反映。

```json
{
    "body": [{
        "type": "container",
        "model": "conditionContainer",
        "children": [{
            "type": "text",
            "text": "只会在等于testA的情况才会触发",
            "style": {
                "display": "block"
            }
        },{
            "type": "select",
            "name": "list",
            "style": {
                "width": 200
            },
            "options": [{
                "key": "testA",
                "value": "A"
            }, {
                "key": "testB",
                "value": "B"
            }, {
                "key": "testC",
                "value": "C"
            }, {
                "key": "testD",
                "value": "D"
            }],
            "trigger": [{
                "event": "onSelect",
                "condition": "#ES{$args.val === 'A'}",
                "targetCustomer": "$this",
                "params": {
                    "result": "#ES{$args.val}"
                },
                "debug": true
            }]
        }, {
            "type": "text",
            "text": "result的值：#ES{$data.result}"
        }]
    }]
}
```



### 强制触发container组件的dataProvider更新
在一些特殊的业务场景模式下，会需要强制让container组件重新从各个dataProvider上获取数据。

比如在表格中嵌入多个表单，当表单提交完成需要刷新当前表格。在这样的情况下，表格和表单是完全不相关的组件。如果没有强制刷新，想通过表单让表格触发数据刷新是件不容易的事情。

如果想触发强制刷新，就直接在事件触发的时候，params里面添加一个特殊参数：$update.

```text
{
    "trigger": [{
        "event": "onClick",
        "targetCustomer": "$this",
        "params": {
            "$update": true
        }
    }]
}
```

上面这个例子中，当某个无状态组件被点击时候，它会把$update: true写入到所属的container组件上，container组件只要接受到$update: true这个指令后，会无视任何数据刷新的判断逻辑，触发container组件上所有的数据源更新。
