折腾:
【未解决】AntD Pro中支持剧本剧本编写时拖动排序单个对话
期间,已经实现了基本的,既支持可拖动实现排序,也支持点击单元格支持实时编辑的表格了:
接下来去优化:
- 去把两种表格的代码合并
- 把模式切换的按钮,放在table内部的底部的左边
- 且参考:
- 单选框 Radio – Ant Design
- https://2x.ant.design/components/radio-cn/
- 去换成 编辑模式 拖动模式 之间通过radio button去切换
- 把分页去掉
- 模式切换时row行高不同,需要优化成相同的行高
去优化
经过一番调试,已经:
- 合并两种表格的代码:最后再贴完整代码
- 去掉了分页:
- 加上了footer:
- 注意一定要个字符串或者函数
现在就剩下:
需要在两种模式切换时,确保高度和对齐等显示效果一致
因为现在是不一致:


需要调节成一致效果
先要去解决:
可编辑的cell的左对齐:

和不可编辑的cell的左对齐:

不一致的问题。
相关代码是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | return ( <td ref = {node = > (this.cell = node)} {...restProps}> {editable ? ( <EditableContext.Consumer> {(form) = > { console.log( "EditableContext.Consumer: form=" , form) this.form = form; return ( editing ? ( <FormItem style = {{ margin: 0 }}> {form.getFieldDecorator(dataIndex, { rules: [{ required: true, message: `${title} is required.`, }], initialValue: record[dataIndex], })( < Input ref = {node = > (this. input = node)} onPressEnter = {this.save} / > )} < / FormItem> ) : ( <div className = {styles.editableCellValueWrap} / / className = {styles.nonEditableCellValueWrap} style = {{ paddingRight: 5 }} onClick = {this.toggleEdit} > {restProps.children} < / div> ) ); }} < / EditableContext.Consumer> ) : restProps.children} < / td> ); |
和:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | @import '~antd/lib/style/themes/default.less' ; .editable-cell { position: relative; } // .nonEditableCellValueWrap { // padding: 5px 12px; // cursor: pointer; // background: grey; // } .editableCellValueWrap { padding: 5px 12px; // padding: 2px 4px; cursor: pointer; } // .editable-row:hover .editableCellValueWrap { // .editableRow:hover .editableCellValueWrap { .editableCellValueWrap:hover { border: 1px solid #d9d9d9; border-radius: 4px; padding: 4px 11px; // padding: 2px 4px; } |
现在去调节
然后最后用:
/src/components/EditableCell/index.js
1 2 3 4 5 6 7 8 9 | // ) : restProps.children} ) : ( <div className={styles.nonEditableCellValueWrap} > {restProps.children} < /div > ) } |
和:
/src/components/EditableCell/index.less
1 2 3 4 5 | .nonEditableCellValueWrap { padding: 5px 12px; cursor: auto; color: darkcyan; } |
达到效果:不可编辑的cell,左边对齐正常了,和可编辑的cell左边一致了:

然后再去解决:
拖拽模式和编辑模式之间,cell高度和padding等不同的情况
而此处注意到之前的EditableTable中是:
1 2 3 4 5 6 | components = { body: { row: EditableFormRow, cell: EditableCell, }, } |
注定了cell用EditableCell,其中EditableCell的render中对单个cell,指定style的
而此处的DragableTable中,没有指定cell:
1 2 3 4 5 | components = { body: { row: DragableBodyRow, }, } |
所以没法直接指定cell的style样式
所以想办法去指定
参考:
去找找,table中是否可以直接指定cell的css
rowClassName
表格行的类名
Function(record, index):string
–
好像是要找的,去看看用法举例
巧了在antd pro中真的找到了实例:
src/routes/Forms/TableForm.js
1 2 3 4 5 6 7 | <Fragment> <Table ... rowClassName={record => { return record.editable ? styles.editable : '' ; }} /> |
和:
/src/routes/Forms/style.less
1 2 3 4 5 6 | .editable { td { padding-top: 13px !important; padding-bottom: 12.5px !important; } } |
所以可以参考这个写法,去试试
然后是可以用代码:
src/components/DragableTable/index.js
1 2 3 4 5 6 7 8 9 | return ( <Table pagination={ false } footer={ this .props.footer} rowClassName={(record, index) => { const curRowStyle = styles.sameWithEditableCell console.log( "rowClassName: record=" , record, " ,index=" , index, ", curRowStyle=" , curRowStyle) return curRowStyle }} |
/src/components/DragableTable/index.less
1 2 3 4 5 6 7 8 9 10 11 12 | @import '~antd/lib/style/themes/default.less' ; .sameWithEditableCell { td { // padding: 5px 12px; // padding: 16px 18px; padding: 21px 28px !important; // color: darkcyan !important; color: darkblue !important; cursor: ns-resize !important; } } |
实现,相同的效果的:


【总结】
至此,用如下代码:
在外部调用合并后的 可拖动可编辑的表格:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | import React, { PureComponent } from 'react' import { connect } from 'dva' import { routerRedux } from 'dva/router' import { Col, Form, Input , Button, Card, InputNumber, Select, message, Modal, / / Checkbox, } from 'antd' import PageHeaderLayout from '../../layouts/PageHeaderLayout' ... / / import DragableTable from '../../components/DragableTable' / / import EditableTable from '../../components/EditableTable' import DragableEditableTable from '../../components/DragableEditableTable' const FormItem = Form.Item; const InputGroup = Input .Group; const { TextArea } = Input ; const { Option } = Select; @connect (({ loading, script, topic }) = > ({ submitting: loading.effects[ 'script/submitRegularForm' ], script, topic, })) @Form .create() export default class ScriptCreate extends PureComponent { constructor(props) { super (props) / / this.onDialogListChange = this.onDialogListChange.bind(this) / / this.onEditableCellChange = this.onEditableCellChange.bind(this) / / this.onDragableCheckChange = this.onDragableCheckChange.bind(this) this.syncDialogList = this.syncDialogList.bind(this) this.onTableModeChange = this.onTableModeChange.bind(this) this.state = { / / dialogList: [], dialogList: this.demoItemList, / / dragableChecked: false, tableMode: DragableEditableTable.TableMode.EDITABLE, ... } } / * eslint - disable * / columns = [ { title: '序号' , width: "8%" , editable: false, dataIndex: 'number' , key: 'number' , / / rowKey: 'number' , / / fixed: 'left' , render(text, record, index) { return index + 1 ; }, }, { width: "15%" , editable: true, title: 'Speaker/Song' , dataIndex: 'speakerOrSong' , key: 'speakerOrSong' , }, { width: "75%" , editable: true, title: 'Content/Name' , dataIndex: 'contentOrName' , key: 'contentOrName' , }, ] demoItemList = [ { key: '1' , speakerOrSong: 'A' , contentOrName: 'hi boy' , editable: true, }, { key: '2' , speakerOrSong: 'B' , contentOrName: 'hello' , editable: true, }, { key: '3' , speakerOrSong: 'A' , contentOrName: 'what are you doing?' , editable: true, }, { key: '4' , speakerOrSong: 'B' , contentOrName: 'I am singing' , editable: true, }, { key: '5' , speakerOrSong: 'Song' , contentOrName: 'this is a apple.mp3' , editable: false, }, ] ... onTableModeChange(e) { console.log( 'onTableModeChange: e.target.value=' , e.target.value); this.setState({ tableMode: e.target.value }) console.log( "after change: this.state.tableMode=" , this.state.tableMode) } syncDialogList(newDialogList){ console.log( "syncDialogList: newDialogList=" , newDialogList) / / console.log( "before change: this.state.dialogList=" , this.state.dialogList) this.setState({dialogList: newDialogList}) console.log( "after change: this.state.dialogList=" , this.state.dialogList) } render() { const { submitting, form } = this.props; const topicList = this.props.topic.topics; const { getFieldDecorator } = this.props.form; ... return ( <PageHeaderLayout title = "新建剧本" > <Card bordered = {false}> ... { / * {this.buildDialog()} * / } { / * { this.state.dragableChecked ? ( <DragableTable columns = {this.columns} itemList = {this.state.dialogList} onDragableListChange = {this.onDialogListChange} / > ) : ( <EditableTable columns = {this.columns} itemList = {this.state.dialogList} onEditableCellChange = {this.onEditableCellChange} form = {this.props.form} / > ) } * / } <DragableEditableTable tableMode = {this.state.tableMode} columns = {this.columns} itemList = {this.state.dialogList} onTableDataChange = {this.syncDialogList} onTableModeChange = {this.onTableModeChange} form = {this.props.form} / > ... < / Form> < / Card> < / PageHeaderLayout> ); } } |
而合并后的表格是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | import React from 'react' import { Radio, } from 'antd' import DragableTable from '../DragableTable' import EditableTable from '../EditableTable' const RadioButton = Radio.Button const RadioGroup = Radio.Group export default class DragableEditableTable extends React.Component { / * eslint - disable * / static TableMode = { EDITABLE: "editable" , DRAGABLE: "dragable" , } / * eslint - disable * / / / static defaultMode = DragableEditableTable.TableMode.DRAGABLE / / static defaultMode = DragableEditableTable.TableMode.EDITABLE / / state = { / / / / mode: this.TableMode.EDITABLE, / / / / mode: this.defaultMode, / / / / mode: DragableEditableTable.defaultMode, / / / / columns: [], / / / / itemList: [], / / } constructor(props){ super (props) / / this.onTableModeChange = this.onTableModeChange.bind(this) / / this.onTableDataChange = this.onTableDataChange.bind(this) this.radioSelectFooter = this.radioSelectFooter.bind(this) console.log( "DragableEditableTable constructor: props=" , props) / / console.log( "this.props.columns=" , this.props.columns) console.log( "this.props.itemList=" , this.props.itemList) console.log( "this.props.tableMode=" , this.props.tableMode) / / this.state.itemList = this.props.itemList / / this.state.columns = this.props.columns / / console.log( "this.state.mode=" , this.state.mode) } / / onTableModeChange(e) { / / console.log( 'onTableModeChange: e.target.value=' , e.target.value); / / this.setState({ / / mode: e.target.value, / / }) / / } / / onTableDataChange(newDialogList){ / / / / update current state / / this.setState({dialogList: newDialogList}) / / / / callback parent to sync state / / this.props.onTableDataChange(newDialogList) / / } / / radioSelectFooter(onRadioChange, defautMode) { radioSelectFooter() { return ( / / <RadioGroup onChange = {this.onTableModeChange} defaultValue = {DragableEditableTable.defaultMode}> / / <RadioGroup onChange = {onRadioChange} defaultValue = {defautMode}> <RadioGroup onChange = {this.props.onTableModeChange} defaultValue = {this.props.tableMode}> <RadioButton value = {DragableEditableTable.TableMode.EDITABLE}>编辑模式< / RadioButton> <RadioButton value = {DragableEditableTable.TableMode.DRAGABLE}>拖动模式< / RadioButton> < / RadioGroup> ) } render() { console.log( "DragableEditableTable render: this.props.itemList=" , this.props.itemList) const commonColumns = this.props.columns const commonItemList = this.props.itemList / / const commonModeSelectorFooter = this.radioSelectFooter(this.props.onTableModeChange, this.props.tableMode) const commonModeSelectorFooter = this.radioSelectFooter const commonDataChange = this.props.onTableDataChange console.log( "commonColumns=" , commonColumns) console.log( "commonItemList=" , commonItemList) console.log( "commonModeSelectorFooter=" , commonModeSelectorFooter) console.log( "commonDataChange=" , commonDataChange) return ( / / { this.props.tableMode = = = DragableEditableTable.TableMode.DRAGABLE ? ( <DragableTable columns = {commonColumns} itemList = {commonItemList} footer = {commonModeSelectorFooter} onDragableListChange = {commonDataChange} / > ) : ( <EditableTable columns = {commonColumns} itemList = {commonItemList} footer = {commonModeSelectorFooter} onEditableCellChange = {commonDataChange} form = {this.props.form} / > ) / / } ) } } DragableEditableTable.defaultProps = { tableMode: DragableEditableTable.TableMode.EDITABLE, itemList: [], onTableDataChange: (newItemList) = > {}, onTableModeChange: (newMode) = > {}, }; |
内部调用的分别是:
/src/components/EditableTable/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | import React from 'react' import { EditableFormRow, EditableCell } from '../EditableCell' import { Table } from 'antd' export default class EditableTable extends React.Component { constructor(props){ super (props) console.log( "EditableTable constructor: props=" , props) console.log( "this.props.columns=" , this.props.columns) console.log( "this.props.itemList=" , this.props.itemList) console.log( "this.props.onEditableCellChange=" , this.props.onEditableCellChange) this.handleSaveEditableCell = this.handleSaveEditableCell.bind(this) this.state.itemList = this.props.itemList; this.state.columns = this.props.columns; } state = { columns: [], itemList: [], } / / componentWillReceiveProps(nextProps){ / / console.log( "EditableTable componentWillReceiveProps: nextProps=" , nextProps) / / console.log( "this.props.itemList=" , this.props.itemList) / / if (this.props.itemList) { / / this.setState({itemList: this.props.itemList}) / / console.log( "updated this.state.itemList=" , this.state.itemList) / / } / / } components = { body: { row: EditableFormRow, cell: EditableCell, }, } handleSaveEditableCell = (row) = > { console.log( "handleSaveEditableCell: row=" , row) const newItemList = [...this.state.itemList] console.log( "newItemList=" , newItemList) const index = newItemList.findIndex(item = > row.key = = = item.key) console.log( "index=" , index) const item = newItemList[index] console.log( "item=" , item) newItemList.splice(index, 1 , { ...item, ...row, }) console.log( "newItemList=" , newItemList) this.setState({ itemList: newItemList }) console.log( "after: this.state.itemList=" , this.state.itemList) this.props.onEditableCellChange(this.state.itemList) / / console.log( "newItemList=" , newItemList) / / this.props.onEditableCellChange(newItemList) } render() { console.log( "EditableTable render: this.state.itemList=" , this.state.itemList) const curColumns = this.state.columns. map ((col) = > { console.log( "curColumns: col=" , col) if (!col.editable) { return col } return { ...col, onCell: (record) = > { / * * Note: * 1. each cell is editable is set by: * first priority: cell editable by each item / cell in this.props.itemList * then check: column editable by each column in this.props.columns * / let cellIsEditable if (record.editable ! = = undefined) { cellIsEditable = record.editable } else { cellIsEditable = col.editable } console.log( "cellIsEditable=" , cellIsEditable, ", record=" , record) return { record, editable: cellIsEditable, dataIndex: col.dataIndex, title: col.title, form: this.props.form, handleSave: this.handleSaveEditableCell, } }, } }) return ( <Table pagination = {false} footer = {this.props.footer} bordered columns = {curColumns} dataSource = {this.state.itemList} components = { this.components } onRow = {(record, index) = > ({ index, })} / > ); } } EditableTable.defaultProps = { itemList: [], onEditableCellChange: (newItemList) = > {}, footer: '', }; |
/src/components/EditableCell/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | import React, { PureComponent } from 'react' ; import styles from './index.less' ; import { Form, Input } from 'antd' ; const FormItem = Form.Item; const EditableContext = React.createContext(); const EditableRow = ({ form, index, ...props }) = > ( <EditableContext.Provider value = {form}> <tr {...props} / > < / EditableContext.Provider> ); export const EditableFormRow = Form.create()(EditableRow); / / export default class EditableCell extends PureComponent { export class EditableCell extends PureComponent { state = { editing: false, } componentDidMount() { console.log( "EditableCell componentDidMount: this.props.editable" , this.props.editable) if (this.props.editable) { document.addEventListener( 'click' , this.handleClickOutside, true); } } componentWillUnmount() { if (this.props.editable) { document.removeEventListener( 'click' , this.handleClickOutside, true); } } toggleEdit = () = > { console.log( "toggleEdit=" ) console.log( "this.state.editing=" , this.state.editing) const editing = !this.state.editing; this.setState({ editing }, () = > { if (editing) { this. input .focus(); } }); } handleClickOutside = (e) = > { const { editing } = this.state; if (editing && this.cell ! = = e.target && !this.cell.contains(e.target)) { this.save(); } } save = () = > { console.log( "save" ) const { record, handleSave } = this.props; console.log( "record=" , record) this.form.validateFields((error, values) = > { console.log( "form.validateFields=: error" , error, ", values=" , values) if (error) { return } this.toggleEdit(); handleSave({ ...record, ...values }); }); } render() { const { editing } = this.state; const { editable, dataIndex, title, record, index, / / handleSave, ...restProps } = this.props; / / console.log( "editing=" , editing, ", editable=" , editable, ", record=" , record) return ( <td ref = {node = > (this.cell = node)} {...restProps}> {editable ? ( <EditableContext.Consumer> {(form) = > { console.log( "EditableContext.Consumer: form=" , form) this.form = form; return ( editing ? ( <FormItem style = {{ margin: 0 }}> {form.getFieldDecorator(dataIndex, { rules: [{ required: true, message: `${title} is required.`, }], initialValue: record[dataIndex], })( < Input ref = {node = > (this. input = node)} onPressEnter = {this.save} / > )} < / FormItem> ) : ( <div className = {styles.editableCellValueWrap} / / className = {styles.nonEditableCellValueWrap} style = {{ paddingRight: 5 }} onClick = {this.toggleEdit} > {restProps.children} < / div> ) ); }} < / EditableContext.Consumer> / / ) : restProps.children} ) : ( <div className = {styles.nonEditableCellValueWrap} > {restProps.children} < / div> ) } < / td> ); } } |
对应less的css:
/src/components/EditableCell/index.less
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | @import '~antd/lib/style/themes/default.less' ; .editable-cell { position: relative; } .nonEditableCellValueWrap { padding: 5px 12px; cursor: auto; // color: darkcyan; color: darkblue; } .editableCellValueWrap { padding: 5px 12px; // padding: 2px 4px; cursor: pointer; // cursor: -webkit-grab; } // .editable-row:hover .editableCellValueWrap { // .editableRow:hover .editableCellValueWrap { .editableCellValueWrap:hover { border: 1px solid #d9d9d9; border-radius: 4px; padding: 4px 11px; // padding: 2px 4px; } |
可拖动的表格:
/src/components/DragableTable/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | import React from 'react' import { Table } from 'antd' import { DragDropContext } from 'react-dnd' import HTML5Backend from 'react-dnd-html5-backend' import update from 'immutability-helper' import DragableBodyRow from '../DragableBodyRow' import styles from './index.less' ; @DragDropContext (HTML5Backend) export default class DragableTable extends React.Component { constructor(props){ super (props) console.log( "DragableTable constructor: props=" , props) console.log( "this.props.columns=" , this.props.columns) console.log( "this.props.itemList=" , this.props.itemList) console.log( "this.props.onDragableListChange=" , this.props.onDragableListChange) this.state.itemList = this.props.itemList; this.state.columns = this.props.columns; } state = { columns: [], itemList: [], } / / componentWillReceiveProps(nextProps){ / / console.log( "DragableTable componentWillReceiveProps: nextProps=" , nextProps) / / console.log( "this.props.itemList=" , this.props.itemList) / / if (this.props.itemList) { / / this.setState({itemList: this.props.itemList}) / / console.log( "updated this.state.itemList=" , this.state.itemList) / / } / / } components = { body: { row: DragableBodyRow, }, } moveRow = (dragIndex, hoverIndex) = > { const { itemList } = this.state; const dragRow = itemList[dragIndex]; this.setState( update(this.state, { itemList: { $splice: [[dragIndex, 1 ], [hoverIndex, 0 , dragRow]], }, }), ) console.log( "moveRow: this.state.itemList=" , this.state.itemList) this.props.onDragableListChange(this.state.itemList) } render() { console.log( "DragableTable render: this.state.itemList=" , this.state.itemList) return ( <Table pagination = {false} footer = {this.props.footer} rowClassName = {(record, index) = > { const curRowStyle = styles.sameWithEditableCell console.log( "rowClassName: record=" , record, " ,index=" , index, ", curRowStyle=" , curRowStyle) return curRowStyle }} bordered columns = {this.state.columns} dataSource = {this.state.itemList} components = { this.components } onRow = {(record, index) = > ({ index, moveRow: this.moveRow, })} / > ); } } DragableTable.defaultProps = { itemList: [], onDragableListChange: (dragSortedList) = > {}, footer: '', }; |
对应less的css:
/src/components/DragableTable/index.less
1 2 3 4 5 6 7 8 9 10 11 12 | @import '~antd/lib/style/themes/default.less' ; .sameWithEditableCell { td { // padding: 5px 12px; // padding: 16px 18px; padding: 21px 28px !important; // color: darkcyan !important; color: darkblue !important; cursor: ns-resize !important; } } |
内部的row:
/src/components/DragableBodyRow/index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | import React from 'react' ; import { DragSource, DropTarget } from 'react-dnd' ; function dragDirection( dragIndex, hoverIndex, initialClientOffset, clientOffset, sourceClientOffset, ) { const hoverMiddleY = (initialClientOffset.y - sourceClientOffset.y) / 2 ; const hoverClientY = clientOffset.y - sourceClientOffset.y; if (dragIndex < hoverIndex && hoverClientY > hoverMiddleY) { return 'downward' ; } if (dragIndex > hoverIndex && hoverClientY < hoverMiddleY) { return 'upward' ; } } class BodyRow extends React.Component { render() { const { isOver, connectDragSource, connectDropTarget, moveRow, dragRow, clientOffset, sourceClientOffset, initialClientOffset, ...restProps } = this.props; const style = { ...restProps.style, cursor: 'move' }; let className = restProps.className; if (isOver && initialClientOffset) { const direction = dragDirection( dragRow.index, restProps.index, initialClientOffset, clientOffset, sourceClientOffset ); if (direction = = = 'downward' ) { className + = ' drop-over-downward' ; } if (direction = = = 'upward' ) { className + = ' drop-over-upward' ; } } return connectDragSource( connectDropTarget( <tr {...restProps} className = {className} style = {style} / > ) ); } } const rowSource = { beginDrag(props) { return { index: props.index, }; }, }; const rowTarget = { drop(props, monitor) { const dragIndex = monitor.getItem().index; const hoverIndex = props.index; / / Don't replace items with themselves if (dragIndex = = = hoverIndex) { return ; } / / Time to actually perform the action props.moveRow(dragIndex, hoverIndex); / / Note: we're mutating the monitor item here! / / Generally it's better to avoid mutations, / / but it's good here for the sake of performance / / to avoid expensive index searches. monitor.getItem().index = hoverIndex; }, }; / / const DragableBodyRow = DropTarget( 'row' , rowTarget, (connect, monitor) = > ({ const DragableBodyRow = DropTarget( 'row' , rowTarget, (connect, monitor) = > ({ connectDropTarget: connect.dropTarget(), isOver: monitor.isOver(), sourceClientOffset: monitor.getSourceClientOffset(), }))( DragSource( 'row' , rowSource, (connect, monitor) = > ({ connectDragSource: connect.dragSource(), dragRow: monitor.getItem(), clientOffset: monitor.getClientOffset(), initialClientOffset: monitor.getInitialClientOffset(), }))(BodyRow) ); export default DragableBodyRow |
从而实现了优化:
- 合并了可拖动的DragableTable和可编辑的EditableTable
- 通过<Table pagination={false}实现了去掉分页
- 通过指定Table的footer实现了显示 radiobutton去切换 两种模式:拖动模式 分页模式
- 通过设置DragableTable的Table的rowClassName,实现了模式切换后表格的样式不变
- 尤其是cell的padding和高度
- 避免了用户在切换后模式后,觉得表格单元格高低不同而觉得太突兀
效果:


切换后:
去拖动:


转载请注明:在路上 » 【已解决】剧本编写系统中优化可拖动排序可编辑单元格的表格