本期葡萄城公開課,將由國電聯合動力技術有限公司,資深前端開發工程師——李林慧女士,與大家在線分享“在 React 框架中使用 SpreadJS 純前端表格控件”的實戰開發經驗。
本節公開課回放
國電聯合動力技術有限公司于2007年6月成立,注冊資本3.13億元,擁有五個全資子公司及五個控股公司,總部位于北京,在全國設有多家生產基地。作為中國國電集團為發展中國綠色能源事業需要,解決風電關鍵、重大設備國產化問題而組建的高新技術公司,國電聯合動力技術有限公司為構建低碳和諧社會、鑄造值得信賴的國產風機品牌提供了強大的技術支持,公司主營業務包括風電機組設計、生產制造、研究開發、銷售服務等。
以下是本期公開課部分精彩內容:
項目背景:
公司采購SpreadJS 純前端表格控件,其主要應用場景是開發一套完善的日常業務流程管理系統,該系統以部門為單位劃分,每周由各部門填報人員,根據系統運行情況、日常運營數據等在系統中進行填報,后交由部門進行數據匯總,并在移動端/PC端系統頁面進行數據展示。
在采購SpreadJS 純前端表格控件之前,公司使用excel進行數據匯總,無法保證各部門的數據流通及時、共享。在經過技術調研后,決定使用SpreadJS(該控件的功能、布局和操作均接近原生Excel)開發業務流程管理系統。通過該系統,部門領導可以實時查看業務運行狀況并給予反饋意見,保證數據流通實時、有效。
選擇SpreadJS的主要原因:
- 功能、布局與Excel高度一致,數據操作、使用習慣均接近原生Excel
- 可在前端導入、導出 Excel 文件,且保持文件的最大完整性
- 支持所有常見的Excel公式函數
本期公開課大綱:
- SpreadJS常用組件及其屬性
- SpreadSheets
- Worksheet
- 渲染過程
- 自定義數據驗證及Demo演示
- 課程答疑
SpreadJS常用組件及其屬性
<SpreadSheets>
<SpreadSheets
backColor="aliceblue"
hostStyle={{ width: `${tableWidth}px`, height: '600px' }}
rowChanged={(_, sheet) => this.handleRowChanged(sheet)}
valueChanged={(_, sheet) => this.handleValueChanged(sheet)}
rangeChanged={(_, sheet) => this.handleRangeChanged(sheet)}
workbookInitialized={spread => this.init(spread)}
>
- rowChanged:主要用于刪除整行觸發,需要判斷 propertyName 屬性
handleRowChanged(content) {// 整行刪除觸發
const {sheet, propertyName} = content
if (propertyName === 'deleteRows') {
const {originalItem: {reportId}} = sheet.getDeletedRows()[0]
if (reportId) {
this.setState({loading: true})
setTimeout(() => {
alert('刪除成功!')
}, 2000)
}
}
- valueChanged:改變單元格值觸發
handleValueChanged(sheet) {
const {changedRow} = this.state
changedRow.push(sheet.row)
this.setState({changedRow: Array.from(new Set(changedRow))})
}
- rangeChanged:輸入公式、delete 刪除數據、移動單元格觸發
handleRangeChanged({ changedCells }) { // 輸入公式、delete刪除數據、移動單元格觸發
const { changedRow } = this.state;
for (let i = 0; i < changedCells.length; i++) {
changedRow.push(changedCells[i].row);
}
this.setState({ changedRow: Array.from(new Set(changedRow)) });
}
- workbookInitialized:初始化表格控件,返回一個 spread 實例
<Worksheet>
<Worksheet dataSource = {data} name="簡單綜合示例" autoGenerateColumns={false}>
{tableHead.length > 0 ? tableHead.map(item => (
<Column
dataField={item.name}
key={item.name}
headerText={item.displayName}
width={item.width}
style={{wordWrap: 'break-wrap', locked: false}}
formatter={item.formatter}
/>
)): null}
</Worksheet>
- dataSource:數據源
- name:工作簿名稱
- <Column>
渲染過程
- workbookInitialized返回一個spread實例,在init方法里可以對options按需進行配置。有了spread實例后也就可以生成一個Excel實例對象,其中包含了常用的spread和spreadNS,以及自定義的一些常用spread方法,比如搜索功能、自適應高度等。
- 從服務器端獲取報表數據后,再根據報表保存的模板id獲取對應的表頭模板,渲染表頭時可以做一些前期工作,如定義選項類的單元格、定義單元格的格式、公式等。
- 將報表數據賦值給Worksheet組件的dataSource屬性。
- 渲染完畢。
自定義數據驗證及Demo演示
數據驗證高亮樣式(Data Validation Highlight Style):SpreadJS 支持自定義數據驗證樣式和不同的單元格突出顯示類型,包括 circle,dogear 和 icon。
數據驗證代碼
// 數據驗證
dataValidate() {
function MyCondition(reg) {
this.reg = reg
GC.Spread.Sheets.ConditionalFormatting.Condition.apply(this, arguments)
}
MyCondition.prototype = new GC.Spread.Sheets.ConditionalFormatting.Condition()
MyCondition.prototype.evaluate = function(evaluator, baseRow, baseColumn, actualObj) {
const reg = new RegExp (this.reg)
if (reg.test(actualObj)) {
return true
}
else {
return false
}
}
// 數據驗證相關變量
const {spread} = this.state,
sheet = spread.getSheet(0),
sheetActive = spread.getActiveSheet(),
nCondition = new MyCondition(/[+-]?\d+(\.\d+)?|^\s+$/),
validator = new GC.Spread.Sheets.DataValidation.DefaultDataValidator(nCondition)
// 數據驗證
spread.suspendPaint()
validator.type(GC.Spread.Sheets.DataValidation.CriteriaType.custom)
spread.options.highlightInvalidData = true
validator.showInputMessage(true)
validator.inputMessage('必須填寫數字!')
validator.inputTitle('提示')
sheetActive.setDataValidator(0, 4, sheet.getRowCount(), 1, validator) // rowIndex, colIndex, rowCount, colCount
sheet.resumePaint()
}
課程答疑Q&A
Q:為何數據量很小,但頁面加載時會出現卡頓
A:凡是涉及到表格重繪的地方最好都用 spread.suspendPaint() 和 spread.resumePaint() 包裹起來,避免頻繁重繪引起卡頓。
Q: 如何渲染多重表頭?
A:Column組件尚未支持多重表頭,針對這個問題,可以在渲染表頭步驟時(此時已獲取到有樹形結構的表頭模板),先給表格setDataSource,獲取所有表頭模板的葉子節點后按列進行表單級別的綁定,然后通過操作表頭區域的賦值、合并單元格等操作手動渲染表頭。
Q:為什么要引入表頭模板?
A:SpreadJS中每一列的列頭顯示的是中文,但是實際上存取對應的是數據庫中的一個字段,所以需要通過數據綁定把表格數據和字段映射起來。其中模板在系統管理內另有維護入口,支持增刪改等基本功能。