# **自定義控件前端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版本。

## **2. 自定義控件2.0生命周期**
自定義控件生命周期大致分為下載、安裝、渲染、更新、銷毀等過程。
- 下載: 表單根據接口返回的控件定義信息`customFieldInfo`下載自定義控件的主js資源及國際化文件
- 安裝: 資源下載完畢后調用控件定義的安裝腳本(install)處理控件的初始化、業務邏輯等
- 渲染: 當表單渲染到該自定義控件時,自定義控件的渲染方法被調用
- 更新: 當控件數據發生變化時,自定義控件的更新方法被調用
- 銷毀: 當控件被表單主動銷毀時,自定義控件的銷毀方法被調用
詳見下圖

## **3. 注冊自定義控件**
用`csdk.component.register(uuid, factory)`申明自定義控件
- uuid: 自定義控件的唯一標識,建議使用`單詞+uuid`實現,保證全局唯一及可讀性
- factory: 自定義控件的具體實現,返回結構參照下圖
```javascript
csdk.component.register('myWidget-12345678', function () {
return {
....
}
});
```
自定義控件的基本代碼結構如下

## **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接口](http://www.hmoore.net/cap4_development/cap-doc/1424196 "csdk API接口")
[csdk 事件接口](http://www.hmoore.net/cap4_development/cap-doc/1424194 "csdk 事件接口")
[csdk 鉤子](http://www.hmoore.net/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
- 自定義控件
- 后端
- 移動端
- 前端編譯
- 表單運行態接口
- 協同云