本期葡萄城公開課,將由國電聯合動力技術有限公司,資深前端開發工程師——李林慧女士,與你們在線分享「在 React 框架中使用 SpreadJS 純前端表格控件」的實戰開發經驗。前端
直播地址:http://live.vhall.com/723418543react
直播時間:2019-07-03(星期三)下午 14:00數據庫
國電聯合動力技術有限公司於2007年6月成立,註冊資本3.13億元,擁有五個全資子公司及五個控股公司,總部位於北京,在全國設有多家生產基地。做爲中國國電集團爲發展中國綠色能源事業須要,解決風電關鍵、重大設備國產化問題而組建的高新技術公司,國電聯合動力技術有限公司爲構建低碳和諧社會、鑄造值得信賴的國產風機品牌提供了強大的技術支持,公司主營業務包括風電機組設計、生產製造、研究開發、銷售服務等。服務器
如下是本期公開課部分精彩內容:app
公司採購SpreadJS 純前端表格控件,其主要應用場景是開發一套完善的平常業務流程管理系統,該系統以部門爲單位劃分,每週由各部門填報人員,根據系統運行狀況、平常運營數據等在系統中進行填報,後交由部門進行數據彙總,並在移動端/PC端系統頁面進行數據展現。框架
在採購SpreadJS 純前端表格控件以前,公司使用excel進行數據彙總,沒法保證各部門的數據流通及時、共享。在通過技術調研後,決定使用SpreadJS(該控件的功能、佈局和操做均接近原生Excel)開發業務流程管理系統。經過該系統,部門領導能夠實時查看業務運行情況並給予反饋意見,保證數據流通實時、有效。函數
SpreadJS經常使用組件及其屬性佈局
<SpreadSheets>this
<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 屬性lua
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>
……
數據驗證高亮樣式(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:凡是涉及到表格重繪的地方最好都用 spread.suspendPaint() 和 spread.resumePaint() 包裹起來,避免頻繁重繪引發卡頓。
Q: 如何渲染多重表頭?
A:Column組件還沒有支持多重表頭,針對這個問題,能夠在渲染表頭步驟時(此時已獲取到有樹形結構的表頭模板),先給表格setDataSource,獲取全部表頭模板的葉子節點後按列進行表單級別的綁定,而後經過操做表頭區域的賦值、合併單元格等操做手動渲染表頭。
Q:爲何要引入表頭模板?
A:SpreadJS中每一列的列頭顯示的是中文,可是實際上存取對應的是數據庫中的一個字段,因此須要經過數據綁定把表格數據和字段映射起來。其中模板在系統管理內另有維護入口,支持增刪改等基本功能。