# **自定义控件前端2.0开发概述**
本文档仅适用于协同版本为V8.0&CAP4.5及以上版本的CAP4表单.
V8.0&CAP4.5前版本的自定义控件前端没有提供统一规范,在实际开发过程基本上是自行发挥,"借鉴"已开发的工程,开发门槛较高,开发者不知如何下手,同时也暴露了一些比较低级的错误。针对这些问题,提出了自定义控件前端2.0规范,定义自定义控件前端的基本生命周期、事件、校验接口等。
自定义控件前端2.0确定了以下内容:
- 注册自定义控件统一接口
- 确定了自定义控件基类,明确了控件的生命周期、事件、API
- 规范基于csdk开放API来操作自定义控件、表单及进行数据通信
- 提供了Promise支持(csdk已经注入polyfill),建议异步操作都使用Promise
## **1. 启用自定义控件2.0**
自定义控件2.0在每个控件上增加了一个`version`属性,`version`设为'2.0'即代表启用自定义控件2.0版本。
![](https://img.kancloud.cn/b1/d2/b1d2624508445dd0f426f393b06c3589_422x192.png)
## **2. 自定义控件2.0生命周期**
自定义控件生命周期大致分为下载、安装、渲染、更新、销毁等过程。
- 下载: 表单根据接口返回的控件定义信息`customFieldInfo`下载自定义控件的主js资源及国际化文件
- 安装: 资源下载完毕后调用控件定义的安装脚本(install)处理控件的初始化、业务逻辑等
- 渲染: 当表单渲染到该自定义控件时,自定义控件的渲染方法被调用
- 更新: 当控件数据发生变化时,自定义控件的更新方法被调用
- 销毁: 当控件被表单主动销毁时,自定义控件的销毁方法被调用
详见下图
![](https://img.kancloud.cn/e1/76/e176c7b2c175215e1d33b13babb58ea4_1270x933.png "自定义控件生命周期图解")
## **3. 注册自定义控件**
用`csdk.component.register(uuid, factory)`申明自定义控件
- uuid: 自定义控件的唯一标识,建议使用`单词+uuid`实现,保证全局唯一及可读性
- factory: 自定义控件的具体实现,返回结构参照下图
```javascript
csdk.component.register('myWidget-12345678', function () {
return {
....
}
});
```
自定义控件的基本代码结构如下
![](https://img.kancloud.cn/d6/95/d69569d7addf0ff8bf152a280923dbd4_1080x1126.png "自定义控件代码结构")
## **4. 生命周期钩子及API详细说明**
下面对自定义控件的生命周期方法详述。
#### **- type**
申明自定义控件实现的类型,可选值raw和vue, 当前版本仅支持raw。
- raw: 原生js实现
- vue: vue组件实现
#### **- plugin.install(context)**
自定义控件资源下载完毕后调用plugin.install(contxt)执行安装脚本,一些常见的业务场景:
- 加载控件使用到的其他资源,如js、css、图片等
- 按次、按量计费的控件,超量超次控件不可使用,在install期间校验
- 从服务器读取控件的相关业务配置
参数/返回值说明:
@param {Object} context {package: '自定义控件控件包地址'},可用于加载包内的资源
@return Promise | undefined | Any
- install方法返回Promise,则表单会等待异步操作完成后才开始渲染自定义控件。
- install方法返回undefined, 表示操作完成。
- install方法返回其他值,表示在安装中遇到错误,无法继续渲染(比如付费服务的调用次数用完)。
示例:
```javascript
// 没有异步,操作成功
plugin: {
install: function (context) {
// 异步操作返回Promise,示例检查接口调用次数是否用完
return new Promise(function (resolve) {
ajax('/xyz/validateApi', {
success: function(res) {
if (res.count <= 0) return; // 次数用完
resolve();
}
})
})
// 安装脚本出错
try {
a.b(); // 模拟报错
} catch (ex) {
return ex || 'unknow error';
}
// 返回undefined,表示没有异步操作且成功
return;
}
}
```
#### **- plugin.requiredAssert(fieldData)**
控件必填校验逻辑,由开发者根据业务需要自行实现,默认校验字段的value是否有值
参数/返回值说明:
@param {Object} fieldData: <FieldData> 自定义控件对象
@return Boolean
#### **- plugin.fieldLengthAssert(fieldData)**
控件长度校验,由开发者根据业务需要自行实现,默认校验通过
参数/返回值说明:
@param {Object} fieldData: <FieldData> 自定义控件对象
@return Boolean
#### **- plugin.validAssert(fieldData)**
控件自定义场景校验,由开发者根据业务需要自行实现,默认校验通过
参数/返回值说明:
@param {Object} fieldData: <FieldData> 自定义控件对象
@return Boolean
#### **- implement.init(context, container)**
控件初始化渲染,由开发者根据自身业务实现控件的渲染,事件绑定等,`该方法必须实现`
参数/返回值说明:
@param {Object} context 初始化渲染上下文参数
@param {HTMLElement} container 控件渲染的容器元素
@return Promise | Any 如果返回Promise, 则控件渲染完成事件会等待promise完成后触发
context参数说明
```javascript
option: {
uuid: '', // 由表单生成唯一标识,用于识别控件实例,进行数据通信
scope: '', // 所在表单视图作用域,用于区分包含视图引用(视图嵌套)场景
fieldId: '', // 控件的数据域id
recordId: '', // 明细行数据id
tableName: '', // 明细表名
container: HTMLElement // 容器元素
}
```
示例:
```javascript
init: function (context, container) {
console.log('init ' + this.$data.display)
var ctx = this;
var el = document.createElement('div');
el.style.cssText = 'padding: 10px 5px; color: white; background: gray';
el.innerHTML = this.$t('cap.form.loading'); // 国际化
setTimeout(function () {
el.innerHTML = 'test ' + ctx.$data.value;
}, 1000);
container.appendChild(el);
this.$el = el;
// 绑定事件
this.$on(this.$el, 'tap', function () {
// 更新数据
ctx.$set({
value: 'event changed ' + Date.now()
});
});
return new Promise(function (resolve) {
// 模拟异步渲染
setTimeout(function () {
this.$el.innerHTML = 'async rendering';
resolve();
}, 1000);
});
}
```
#### **- implement.update()**
当控件数据发生变化时,会触发该方法,由开发者实现渲染更新
示例:
```javascript
update: function () {
this.$el.innerHTML = 'updated at ' + Date.now() + '\n,new value is: ' + this.$data.value;
}
```
#### **- implement.destroy()**
在控件被销毁前调用,由开发实现需要清理的事件、数据等
示例:
```javascript
destroy: function () {
console.log('destroy ' + this.$data.display)
this.$el = null;
}
```
#### **- implement.beforeSave()**
在表单保存时调用,由开发者实现当前控件需要在保存前的业务处理
参数说明:
@return Promise | Any 如果返回Promise,则表单会等待异步操作完成继续提交
<small>注1: 由于交互问题,移动端轻表单模式只支持调用主表中的自定义控件该方法</small>
<small>注2: 由于数据分页,只支持调用在页面渲染好的(即可见)控件的该方法</small>
<small>注3: 除非特殊需要,尽可能减少这种场景设计</small>
示例:
```javascript
beforeSave: function () {
console.log('beforeSave ' + this.$data.display);
return new Promise((resolve) => {
// do sth cost 2 seconds
setTimeout(resolve, 2000);
});
}
```
#### **- implement.afterSave()**
表单提交后调用该方法,由于保存后页面会关闭或者刷新,只建议实现同步调用
示例:
```javascript
afterSave: function () {
console.log('Saved');
}
```
#### **- $t(i18nKey, replacer)**
获取国际化词条
```javascript
fI18nData['cap.form.mywidget.chineseDate'] = '{0}年{1}月';
this.$t('cap.form.mywidget.chineseDate', ['2020', '4']);
```
#### **- $set(data)**
更新当前控件数据
示例:
```javascript
data = {
value: 'value', // 控件的值
display: 'showValue', // 控件的显示值
auth: 'auth', // 控件的权限
atts: Object, // 待定,尚未完全支持
placeholder: 'placeHolder' // 输入框占位符
};
this.$set({
value: 'newValue',
display: 'newShowValue',
auth: 'browse'
})
```
#### **- $on(el, type, listener) 和 $on(type, listener)**
控件事件绑定,支持绑定dom事件和控件自定义事件,使用方式如下:
- $on(el, type, listener) : 绑定dom事件
- $on(type, listener) : 绑定控件自定义事件
_调用this.$on绑定的事件,在控件销毁时,会被自动销毁,开发者无须关注_
#### **- $emit(type, data)**
控件触发自定义事件
## **5. 自定义控件事件**
EVENT_RENDERED: 自定义控件渲染完,需开发者保证
EVENT_UPDATED: 自定义控件更新完成
EVENT_DESTROYED: 自定义控件销毁
示例:
```javascript
csdk.event.on(csdk.component.EVENT_RENDERED, function(evt) {
console.log('component rendered', evt);
});
```
## **6. 与表单、其他控件交互通信**
与自定义控件1.0版本相比,2.0版本只在初始化提供必要参数,1.0版本中提供的一些其他数据不再传入。如需要获取表单数据、获取其他控件数据、更新表单、更新其他控件(包括自定义控件自身)、监听数据变化等请使用表单提供的csdk开发套件。[csdk](http://example.com/ "csdk").开发套件提供了一套PC和移动一致的API及事件,可实现大部分代码重用。
csdk相关文档见:
[csdk API接口](https://www.kancloud.cn/cap4_development/cap-doc/1424196 "csdk API接口")
[csdk 事件接口](https://www.kancloud.cn/cap4_development/cap-doc/1424194 "csdk 事件接口")
[csdk 钩子](https://www.kancloud.cn/cap4_development/cap-doc/1424195 "csdk 钩子")
*End*
- 概要
- 技术介绍
- 框架与环境
- vue开发
- 开发规范
- 前端开发规范
- 总体原则
- HTML规范
- HTML&css规范
- vue编码规范
- Javascript规范
- 后端开发规范
- cap4
- 自定义控件
- 前端2.0(PC+移动)
- PC前端
- 后端
- 移动端
- 移动端接口
- 低版本协同升级到V5 8.0适配说明
- 自定义按钮
- 自定义按钮(无流程)
- 自定义控件(列表插槽)
- 自定义按钮(筛选条件)
- 低版本协同升级到V5 8.0适配说明
- 门户空间
- 门户与栏目挂载
- 栏目开发及流程说明
- 页面模板
- 客开通路及插件体系
- 表单设计器扩展配置
- 使用步骤
- 配置说明
- 事件API
- Demo示例
- 运行态客开通路
- 插件使用步骤
- 插件接口
- 事件接口
- 钩子相关接口
- 表单操作接口
- Demo示例
- 插件机制
- 表单运行态接口(旧)
- 白名单插件
- 版本记录
- vue组件库
- 开发指南
- 开发文档规范
- 业务组件介绍
- 业务组件
- table组件
- 分页组件
- title组件
- 统计排队组件
- code组件
- 条件筛选
- 批量导入
- 上传Excel
- 批量更新
- 批量刷新
- UI组件
- 按钮组件
- 复选组件
- 取色器组件
- 示例组件
- 水平选择组件
- 选图标组件
- 提示组件
- 单选组件
- 搜索组件
- 选择组件
- 穿梭框组件
- 标签组件
- 文本组件
- 树组件
- 验证组件
- 菜单组件
- iframe组件
- toolbar
- 统计组件
- 饼图
- 柱状图
- 图标
- 业务关系开发指南
- 自定义触发
- 自定义关联
- 后端API
- 更新表单数据缓存
- 发起表单流程
- 取得指定表单PDF或截图
- 无流程批量添加
- 无流程批量删除
- 无流程批量更新
- 无流程批量导出
- 客开培训文档
- Vue基础培训
- Vue实战培训
- Vue进阶培训
- VueCLI3培训
- cap3
- 自定义控件
- 后端
- 移动端
- 前端编译
- 表单运行态接口
- 协同云