2020-07-28 10:03:53 +08:00
|
|
|
|
---
|
|
|
|
|
title: 联动
|
2020-07-29 16:20:21 +08:00
|
|
|
|
description:
|
2020-07-28 10:03:53 +08:00
|
|
|
|
type: 0
|
|
|
|
|
group: 💡 概念
|
|
|
|
|
menuName: 联动
|
2020-07-29 16:20:21 +08:00
|
|
|
|
icon:
|
2020-07-28 10:03:53 +08:00
|
|
|
|
order: 14
|
|
|
|
|
---
|
2020-07-29 16:20:21 +08:00
|
|
|
|
|
2020-07-28 10:03:53 +08:00
|
|
|
|
上一节我们介绍了表达式的概念,而表达式应用最多的场景,是实现页面的联动效果。
|
|
|
|
|
|
|
|
|
|
## 基本联动
|
|
|
|
|
|
|
|
|
|
元素的联动是页面开发中很常见的功能之一,类似于:
|
|
|
|
|
|
|
|
|
|
- 某个条件下显示或隐藏某个组件
|
|
|
|
|
- 某个条件下请求接口
|
|
|
|
|
- 某个条件下轮训接口停止轮训
|
|
|
|
|
- 等等...
|
|
|
|
|
|
2020-07-29 16:20:21 +08:00
|
|
|
|
> 联动配置项一般都是 [表达式](../concepts/expression)
|
2020-07-28 10:03:53 +08:00
|
|
|
|
|
|
|
|
|
### 组件配置联动
|
|
|
|
|
|
|
|
|
|
控制组件的显隐,表单项的禁用状态等,看下面这个例子:
|
|
|
|
|
|
|
|
|
|
```schema:height="300" scope="body"
|
|
|
|
|
{
|
|
|
|
|
"type": "form",
|
|
|
|
|
"controls": [
|
|
|
|
|
{
|
|
|
|
|
"type": "radios",
|
|
|
|
|
"name": "foo",
|
|
|
|
|
"label": false,
|
|
|
|
|
"options": [
|
|
|
|
|
{
|
|
|
|
|
"label": "类型1",
|
|
|
|
|
"value": 1
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"label": "类型2",
|
|
|
|
|
"value": 2
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"type": "text",
|
|
|
|
|
"name": "text1",
|
|
|
|
|
"label": false,
|
|
|
|
|
"placeholder": "选中 类型1 时可见",
|
|
|
|
|
"visibleOn": "data.foo == 1"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"type": "text",
|
|
|
|
|
"name": "text2",
|
|
|
|
|
"label": false,
|
|
|
|
|
"placeholder": "选中 类型2 时不可点",
|
|
|
|
|
"disabledOn": "data.foo == 2"
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
上面实例主要为一个表单,表单内有三个组件:一个`radio`, 两个`text`,通过配置联动配置项,实现下面联动效果:
|
2020-07-29 16:20:21 +08:00
|
|
|
|
|
2020-07-28 10:03:53 +08:00
|
|
|
|
1. 只要当`radio`选中`类型1`时,才会显示`text1`;
|
|
|
|
|
2. 当`radio`选中`类型2`时,`text2`将会变为`禁用状态`
|
|
|
|
|
|
2020-07-29 16:20:21 +08:00
|
|
|
|
> **注意:**
|
|
|
|
|
>
|
2020-07-28 10:03:53 +08:00
|
|
|
|
> 在表单项联动中,为了方便数据的读取,赋值后或者修改过的表单项,通过隐藏后,并不会在当前数据域中删除掉该字段值,因此默认提交的时候可能仍然会带上已隐藏表单项的值
|
2020-07-29 16:20:21 +08:00
|
|
|
|
>
|
|
|
|
|
> 如果想要在提交时去掉某个隐藏的字段,可以通过 [数据映射](./data-mapping) 配置自定义数据体
|
2020-07-28 10:03:53 +08:00
|
|
|
|
|
|
|
|
|
### 接口联动
|
|
|
|
|
|
|
|
|
|
#### 基本使用
|
|
|
|
|
|
|
|
|
|
接口联动是另外一种很常见的场景,查看下面这个例子:
|
|
|
|
|
|
|
|
|
|
```schema:height="250" scope="body"
|
|
|
|
|
{
|
|
|
|
|
"title": "",
|
|
|
|
|
"type": "form",
|
|
|
|
|
"mode": "horizontal",
|
|
|
|
|
"controls": [
|
|
|
|
|
{
|
|
|
|
|
"label": "选项1",
|
|
|
|
|
"type": "radios",
|
|
|
|
|
"name": "a",
|
|
|
|
|
"inline": true,
|
|
|
|
|
"options": [
|
|
|
|
|
{
|
|
|
|
|
"label": "选项A",
|
|
|
|
|
"value": 1
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"label": "选项B",
|
|
|
|
|
"value": 2
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"label": "选项C",
|
|
|
|
|
"value": 3
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"label": "选项2",
|
|
|
|
|
"type": "select",
|
|
|
|
|
"size": "sm",
|
|
|
|
|
"name": "b",
|
|
|
|
|
"source": "https://houtai.baidu.com/api/mock2/options/level2?a=${a}",
|
|
|
|
|
"description": "切换<code>选项1</code>的值,会触发<code>选项2</code>的<code>source</code> 接口重新拉取"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"actions": []
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
上面例子我们实现了这个逻辑:每次选择`选项1`的时候,会触发`选项2`的`source`配置的接口重新请求,并返回不同的下拉选项。
|
|
|
|
|
|
|
|
|
|
是如何做到的?
|
|
|
|
|
|
2020-07-29 16:20:21 +08:00
|
|
|
|
实际上,所有**初始化接口链接上使用数据映射获取参数的形式**时,例如下面的`query=${query}`,在当前数据域中,**所引用的变量值(即 query)发生变化时**,自动重新请求该接口。
|
2020-07-28 10:03:53 +08:00
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"initApi": "/api/initData?query=${query}"
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
> **tip:**
|
2020-07-29 16:20:21 +08:00
|
|
|
|
>
|
2020-07-28 10:03:53 +08:00
|
|
|
|
> 触发所引用变量值发生变化的方式有以下几种:
|
2020-07-29 16:20:21 +08:00
|
|
|
|
>
|
2020-07-28 10:03:53 +08:00
|
|
|
|
> 1. 通过对表单项的修改,可以更改表单项`name`属性值所配置变量的值;
|
|
|
|
|
> 2. 通过[组件间联动](./linkage#%E7%BB%84%E4%BB%B6%E9%97%B4%E8%81%94%E5%8A%A8),将其他组件的值发送到目标组件,进行数据域的更新,从而触发联动效果
|
2020-07-29 16:20:21 +08:00
|
|
|
|
>
|
2020-07-28 10:03:53 +08:00
|
|
|
|
> 接口联动一般只适用于初始化接口,例如:
|
2020-07-29 16:20:21 +08:00
|
|
|
|
>
|
2020-07-28 10:03:53 +08:00
|
|
|
|
> - `form`组件中的`initApi`;
|
|
|
|
|
> - `select`组件中的`source`选项源接口;
|
|
|
|
|
> - `service`组件中的`api`和`schemaApi`;
|
|
|
|
|
> - `crud`组件中的`api`;
|
|
|
|
|
> - 等等...
|
|
|
|
|
|
|
|
|
|
#### 配置请求条件
|
|
|
|
|
|
|
|
|
|
默认在变量变化时,总是会去请求联动的接口,你也可以配置请求条件,当只有当前数据域中某个值符合特定条件才去请求该接口。
|
|
|
|
|
|
|
|
|
|
```schema:height="250" scope="body"
|
|
|
|
|
{
|
|
|
|
|
"title": "",
|
|
|
|
|
"type": "form",
|
|
|
|
|
"mode": "horizontal",
|
|
|
|
|
"controls": [
|
|
|
|
|
{
|
|
|
|
|
"label": "选项1",
|
|
|
|
|
"type": "radios",
|
|
|
|
|
"name": "a",
|
|
|
|
|
"inline": true,
|
|
|
|
|
"options": [
|
|
|
|
|
{
|
|
|
|
|
"label": "选项A",
|
|
|
|
|
"value": 1
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"label": "选项B",
|
|
|
|
|
"value": 2
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"label": "选项C",
|
|
|
|
|
"value": 3
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"label": "选项2",
|
|
|
|
|
"type": "select",
|
|
|
|
|
"size": "sm",
|
|
|
|
|
"name": "b",
|
|
|
|
|
"source": {
|
|
|
|
|
"method": "get",
|
|
|
|
|
"url": "https://houtai.baidu.com/api/mock2/options/level2?a=${a}",
|
|
|
|
|
"sendOn": "data.a === 2"
|
|
|
|
|
},
|
|
|
|
|
"description": "只有<code>选项1</code>选择<code>B</code>的时候,才触发<code>选项2</code>的<code>source</code>接口重新拉取"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"actions": []
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
更多用法,见:[Api-配置请求条件](./types-api#%E9%85%8D%E7%BD%AE%E8%AF%B7%E6%B1%82%E6%9D%A1%E4%BB%B6)
|
|
|
|
|
|
|
|
|
|
#### 主动触发
|
|
|
|
|
|
|
|
|
|
上面示例有个问题,就是数据一旦变化就会出发重新拉取,而输入框的频繁变化值会导致频繁的拉取?没关系,也可以配置主动拉取如:
|
|
|
|
|
|
|
|
|
|
```schema:height="300" scope="body"
|
|
|
|
|
{
|
|
|
|
|
"type": "form",
|
|
|
|
|
"name": "my_form",
|
|
|
|
|
"controls": [
|
|
|
|
|
{
|
|
|
|
|
"type": "text",
|
|
|
|
|
"name": "keyword",
|
|
|
|
|
"addOn": {
|
|
|
|
|
"label": "搜索",
|
|
|
|
|
"type": "button",
|
|
|
|
|
"actionType": "reload",
|
|
|
|
|
"target": "my_form.select"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"type": "select",
|
|
|
|
|
"name": "select",
|
|
|
|
|
"label": "Select",
|
|
|
|
|
"source": {
|
|
|
|
|
"method": "get",
|
|
|
|
|
"url": "https://houtai.baidu.com/api/mock2/form/getOptions?waitSeconds=1",
|
|
|
|
|
"data": {
|
|
|
|
|
"a": "${keyword}"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
1. 通过`api`对象形式,将获取变量值配置到`data`请求体中。
|
|
|
|
|
2. 配置搜索按钮,并配置该行为是刷新目标组件,并配置目标组件`target`
|
|
|
|
|
3. 这样我们只有在点击搜索按钮的时候,才会将`keyword`值发送给`select`组件,重新拉取选项
|
|
|
|
|
|
|
|
|
|
### 其他联动
|
|
|
|
|
|
2020-07-29 16:20:21 +08:00
|
|
|
|
还有一些组件特有的联动效果,例如 form 的 disabledOn,crud 中的 itemDraggableOn 等等,可以参考相应的组件文档。
|
2020-07-28 10:03:53 +08:00
|
|
|
|
|
|
|
|
|
## 组件间联动
|
|
|
|
|
|
|
|
|
|
联动很可能会出现跨组件的形式,思考下面这种场景:
|
|
|
|
|
|
|
|
|
|
有一个表单`form`组件,还有一个列表组件`crud`,我们想要把`form`提交的数据,可以用作`crud`的查询条件,并请求`crud`的接口,由于`form`和`crud`位于同一层级,因此没法使用数据链的方式进行取值。
|
|
|
|
|
|
|
|
|
|
```schema:height="800" scope="body"
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
"title": "查询条件",
|
|
|
|
|
"type": "form",
|
|
|
|
|
"controls": [
|
|
|
|
|
{
|
|
|
|
|
"type": "text",
|
|
|
|
|
"name": "keywords",
|
|
|
|
|
"label": "关键字:"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"submitText": "搜索"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"type": "crud",
|
|
|
|
|
"api": "https://houtai.baidu.com/api/sample",
|
|
|
|
|
"columns": [
|
|
|
|
|
{
|
|
|
|
|
"name": "id",
|
|
|
|
|
"label": "ID"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"name": "engine",
|
|
|
|
|
"label": "Rendering engine"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"name": "browser",
|
|
|
|
|
"label": "Browser"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"name": "platform",
|
|
|
|
|
"label": "Platform(s)"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"name": "version",
|
|
|
|
|
"label": "Engine version"
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
现在更改配置如下:
|
|
|
|
|
|
|
|
|
|
```schema:height="800" scope="body"
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
"title": "查询条件",
|
|
|
|
|
"type": "form",
|
|
|
|
|
"target": "my_crud",
|
|
|
|
|
"controls": [
|
|
|
|
|
{
|
|
|
|
|
"type": "text",
|
|
|
|
|
"name": "keywords",
|
|
|
|
|
"label": "关键字:"
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"submitText": "搜索"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"type": "crud",
|
|
|
|
|
"name": "my_crud",
|
|
|
|
|
"api": "https://houtai.baidu.com/api/sample",
|
|
|
|
|
"columns": [
|
|
|
|
|
{
|
|
|
|
|
"name": "id",
|
|
|
|
|
"label": "ID"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"name": "engine",
|
|
|
|
|
"label": "Rendering engine"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"name": "browser",
|
|
|
|
|
"label": "Browser"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"name": "platform",
|
|
|
|
|
"label": "Platform(s)"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"name": "version",
|
|
|
|
|
"label": "Engine version"
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
我们进行两个调整:
|
2020-07-29 16:20:21 +08:00
|
|
|
|
|
2020-07-28 10:03:53 +08:00
|
|
|
|
1. 为`crud`组件设置了`name`属性为`my_crud`
|
|
|
|
|
2. 为`form`组件配置了`target`属性为`crud`的`name`:**`my_crud`**
|
|
|
|
|
|
2020-07-29 16:20:21 +08:00
|
|
|
|
更改配置后,提交表单时,如果有配置提交接口,会先请求提交,之后 amis 会寻找`target`所配置的目标组件,把`form`中所提交的数据,发送给该目标组件中,并将该数据**合并**到目标组件的数据域中,并触发目标组件的刷新操作,对于 CRUD 组件来说,刷新即重新拉取数据接口。
|
2020-07-28 10:03:53 +08:00
|
|
|
|
|
|
|
|
|
> 当然,`crud`组件内置已经支持此功能,你只需要配置`crud`中的`filter`属性,就可以实现上面的效果,更多内容查看 [crud -> filter](./crud) 文档。
|
|
|
|
|
|
|
|
|
|
我们再来一个例子,这次我们实现两个`form`之间的联动:
|
|
|
|
|
|
|
|
|
|
事实上,**组件间联动也可以实现上述任意的 [基本联动效果](./linkage#%E5%9F%BA%E6%9C%AC%E8%81%94%E5%8A%A8)(显隐联动、接口联动等其他联动)。**
|