react 拖拽功能
用法简介
-
基于react的拖拽功能,有这么几个比较流行的库:
- react-dnd
- react-beautiful-dnd
- dnd-kit
- react-sortable-hoc
介绍react-sortable-hoc 用法
-
下载==>(项目中安装 react-sorting-hoc 以及 array-move,后者是用来实现数组移动。)
- yarn add react-sortable-hoc array-move
- npm add react-sortable-hoc array-move
-
项目页面中引入包
- import {sortableContainer, sortableElement} from 'react-sortable-hoc';
- import arrayMove from 'array-move';
-
基本概念
- SortableContainer 拖拽排序的容器
- SortableElement 拖拽排序的元素
-
用法
- 在 render 里写
<SortableContainer distance={10} items={sendMsgList || []} onSortEnd={this.onSortEnd} />
// items里存放需要便利拖拽的数组
// distance属性 作用:(设置触发排序之前要拖动的最小距离) eg:可以设置为10px
- 目的:防止拖拽组件里的onClick时间不能触发
// 列表拖动
onSortEnd = ({oldIndex, newIndex}) => { const {sendMsgList} = enterpriseMicroSOP.addTeskNode; if (oldIndex !== newIndex) { const newData = arrayMove([].concat(sendMsgList), oldIndex, newIndex).filter(el => !!el); enterpriseMicroSOP.addTeskNode.sendMsgList = JSON.parse(JSON.stringify(newData)); } };
const SortableContainer = sortableContainer(({items}) => { return ( <div className={style.Timeline_info} ref={this.listRef} onScrollCapture={() => this.handleScroll()}> {items.map((item_, index_) => { if (item_.sendType == 0) { return <RenderTextInfo key={`item-${index_}`} index={index_} index_={index_} item_={item_} disabled={false} />; } })} </div> ); });
- 需要创建一个ref节点 目的是为了拖拽滚动的时候,滚动位置不变
this.listRef = React.createRef();
componentDidUpdate() { // 滚动位置不变 this.listRef.current.scrollTop = this.scrollTop; }
- 需要排序的元素(也要写在render里面)
const RenderTextInfo = sortableElement(({item_, index_}) => { return ( <div className={style.list_template} key={index_}> <div className={style.left}> <div className={style.list_template_left}> <span>{index_ + 1}</span> </div> <div className={style.text_info}>{item_.sendTypeMessage}</div> </div> </div> ); });
介绍react-beautiful-dnd 用法
-
下载
- yarn add react-beautiful-dnd
- npm install react-beautiful-dnd --save
-
项目页面中引入包
- import {DragDropContext, Droppable, Draggable} from 'react-beautiful-dnd';
-
基本用法
- DragDropContext : 用于包装拖拽根组件,Draggable和Droppable都需要包裹在DragDropContext内
- Draggable 用于包装你需要拖动的组件,使组件能够被拖拽(make it draggable)
- Droppable 用于包装接收拖拽元素的组件,使组件能够放置(dropped on it)
return ( <DragDropContext onDragEnd={this.handleDragEnd}> <Droppable droppableId="droppable"> {(provided, snapshot) => ( <div {...provided.droppableProps} ref={provided.innerRef} className={style.drop_col_container} key={'droppable'}> {typeList.map((item, index) => { if (this.props.isCustomerGroup) { if (item.typeKey == 'file' || item.typeKey == 'miniprogram') return; } return ( <Draggable key={item.id} draggableId={String(item.id)} index={index}> {(provided, snapshot) => ( <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} key={index} className={`${style.drop_item} ${this.state.activeKey == item.typeKey ? style.drop_item_selected : ''}`}> <div className={style.drop_col}> <div className="drop"></div> <TextArea id={'SortName'} className="SortName" onChange={e => { this.handleInputChange(e, item.typeKey); }} value={item.typeName} showCount placeholder="请输入名称" maxLength={10} rows={1} /> </div> </div> )} </Draggable> ); })} </div> )} </Droppable> </DragDropContext> );
handleDragEnd = result => { const {typeList} = this.state; if (!result.source || !result.destination) return; const sourceIndex = result.source.index; // 被拖动元素位置 const endIndex = result.destination.index; // 拖动的位置 const list = this.swapArr(typeList, sourceIndex, endIndex); this.setState({typeList: list}); };
swapArr(arr, index1, index2) { if (index1 > index2) { arr.splice(index2, 0, arr[index1]); arr.splice(index1 + 1, 1); } else { arr.splice(index2 + 1, 0, arr[index1]); arr.splice(index1, 1); } return arr; }