1、問題描述javascript
問題是這樣的,後臺傳了xArr = [x1, x2,...,xn]和yArr = [y1, y2, ..yn]兩個數組,前端要渲染出表格而且能夠填寫每一個單元格的值,而後按照必定數據結構保存並傳給後臺,而且再次獲取這個數據結構和數組xArr、yArr能夠本身渲染出這個表?實現新增和修改的功能。大體界面效果以下圖所示:前端
y1, y2,...,yn做爲列名,x1,x2, ..., xn做爲第一列數據,此業務模型是一種常見的表格,只不過要求行列都不固定,由後臺數據提供而且動態生成。還要可以實現修改功能。本質上是一個動態渲染可編輯Table的問題。難點在於動態構建表格而且實現數據展現和保存。java
2、解決思路react
(1)數據轉換成表格後,處理起來就簡單了,若是以常見的Table組件爲例,只須要構建columns和dataSource兩個數組數據便可渲染出表格;數組
(2)渲染出表格後,表格每個餘下的單元格都要可輸入,能夠考慮單元格利用render渲染出Input組件,經過Input的操做onChange或onBlur去改變數據並存儲。antd
(3)數組是引用類型,能夠利用引用類型只要沒有深拷貝或改變指針指向內存地址就不變的原理,方便記錄操做後的數據。數據結構
3、解決方法(以React結合ant design UI的Table組件爲例):this
(1)動態構建columns(表格列數據)和dataSource(表格數據源)渲染出表格。(Table可參考 https://ant.design/components/table-cn/#header)spa
1 const xArr = ['x1', 'x2', 'x3', 'x4']; 2 const dataSource = xArr.map((v, i) => ({ 3 key: String(i),//此處自定義表格每一行的惟一key,若是沒有設置惟一標誌會報錯 4 y0: v,//第一列數據即顯示X1-Xn的那一列 5 })); 6 7 const yArr = ['y1', 'y2', 'y3', 'y4', 'Y5']; 8 const columns = [{ 9 title: ' ', 10 dataIndex: 'y0',//第一列y0爲列的dataIndex,用於顯示x1-xn 11 }, ...yArr.map(item => ({//其餘列經過yArr循環獲得,並用...解構直接合併爲columns 12 title: item, 13 dataIndex: item, 14 }))];
這樣就獲得形如dataSource = [{ key: '0', y0:'x1'}, { key: '0', y0:'x1'},...]; columns = [{ title: '', dataIndex: 'y0'},{ title: 'y1', dataIndex: 'y1'},...];的表格數據,將此數據源傳入表格組件Table,便可渲染出表格以下:指針
<Table columns={columns} dataSource={dataSource} />
(2)表格添加Input而且根據onChange/onBlur事件動態記錄dataSource的變化。
1 const columns = [{ 2 title: ' ', 3 dataIndex: 'y0', 4 }, ...yArr.map(item => ({ 5 title: item, 6 dataIndex: item, 7 render: (text, record) => ( 8 <Input defaultValue={record[item]} onChange={(e) => { record[item] = e.target.value; }} /> 9 ), 10 }))];
渲染效果以下:
4、完整代碼
/** * @author xiao-pengyou * @create date 2019-03-27 * @desc 動態可編輯表格 * */ import React, { PureComponent } from 'react'; import { Table, Input } from 'antd'; export default class Demo extends PureComponent { state = { dataSource: [] }; componentDidMount() { const xArr = ['x1', 'x2', 'x3', 'x4']; const dataSource = xArr.map((v, i) => ({key: String(i),y0: v})); this.setState({ dataSource });//dataSource不能在render裏面構建,在render裏面構建每次從新渲染的時候dataSource會被從新構建,指針指向變化致使先前的修改不能被跟蹤 } render() { const yArr = ['y1', 'y2', 'y3', 'y4', 'y5']; const that = this;//定義中間量that=this確保columns內部onChange事件做用域爲當前組件,方便調用forceUpdate()強制渲染表格 const columns = [{ title: ' ', dataIndex: 'y0', }, ...yArr.map(item => ({ title: item, dataIndex: item, render: (text, record) => ( <Input value={record[item]} onChange={(e) => { record[item] = e.target.value; that.forceUpdate(); }} /> ), }))];//最終的dataSource就是咱們想要的數據結構,修改時直接把這個dataSource傳給構建的表格就能夠渲染 return <Table columns={columns} dataSource={this.state.dataSource} bordered pagination={false} />;//bordered設置邊框,pagination=false取消分頁功能,能夠不用在乎此參數 } }
最終效果(控制檯輸出爲提交給後臺的dataSource數組):
以上就是一個動態列的可編輯表格的React實現方式。若有問題歡迎留言批評指正,謝謝!
本文爲原創博客,非法抄襲或複製將追究法律責任,轉載請註明出處:https://www.cnblogs.com/xiao-pengyou/