react?實(shí)現(xiàn)表格列表拖拽排序的示例
問題描述
在項(xiàng)目開發(fā)中,遇到這樣一個(gè)需求:需要對(duì)表格里面的數(shù)據(jù)進(jìn)行拖拽排序。
效果圖如下所示:
思路
安裝兩個(gè)插件:
- react-sortable-hoc (或者 react-beautiful-dnd)
- array-move
npm install --save react-sortable-hoc npm install --save array-move
解析
1. react-sortable-hoc
react-sortable-hoc
是一組 react
高階組件(參數(shù)或返回值為函數(shù)),用于實(shí)現(xiàn)拖動(dòng)排序功能,可以將任何列表轉(zhuǎn)換為動(dòng)畫,可訪問和觸摸友好的可排序列表??梢院同F(xiàn)有組件集成,支持拖動(dòng)手柄、自動(dòng)滾動(dòng)、鎖定軸和操作事件等功能,有著流程的動(dòng)畫效果??伤?、垂直拖動(dòng)。
react-sortable-hoc 的使用:
react-sortable-hoc
提供了兩個(gè)特別重要的API
- SortableContainer :是所有可拖拽排序元素的容器
- SortableElement :是每個(gè)要拖拽排序元素的容器
- SortableHandle :是定義拖拽手柄的容器
import { SortableHandle } from 'react-sortable-hoc'; import { MenuOutlined } from '@ant-design/icons'; const DragHandle = SortableHandle(() => <MenuOutlined style={{ cursor: 'grab', color: '#999' }} />) { title: '拖動(dòng)排序', dataIndex: 'sort', width: 120, align: 'center', className: 'drag-visible', editable: false, render: () =>{ if (editable) return <DragHandle />; return <span>禁止拖動(dòng)</span> }, },
SortableHandle 就是指下面的箭頭部分
SortableElement
提供了一個(gè) index
屬性來(lái)進(jìn)行對(duì)每個(gè)要拖拽元素的排序
SortableContainer
提供一個(gè)方法 onSortEnd
,這個(gè)方法可以解構(gòu)兩個(gè)形參:{ oldIndex , newIndex }
,一個(gè)是拖拽元素的標(biāo)記,一個(gè)是將要放的地方的標(biāo)記。
最后在使用 arrayMoveImmutable
交換數(shù)組的位置。
axis 表示拖拽的方向,x 是水平拖拽,y 是垂直拖拽,默認(rèn)是垂直拖拽
2. array-move
array-move
其實(shí)就是一個(gè) API,它的主要作用是用來(lái)交換數(shù)組中元素的位置。
看下面的實(shí)例:
// 在tsx文件中 import React, { useEffect } from 'react'; import { arrayMoveImmutable } from 'array-move'; const Index = () => { useEffect(() => { let arr = ['a', 'b', 'c'] let result = arrayMoveImmutable(arr, 1 , 2) console.log(result) // 結(jié)果輸入為: [ 'a', 'c', 'b' ] }) } export default Index
使用
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc'; import { arrayMoveImmutable } from 'array-move'; // 定義拖拽的table 容器 const DragTableContainer = SortableContainer((props) => <tbody {...props}>) // 定義 拖拽的 行 const DragTableItem = SortableElement((props) => <tr {...props}>) // 定義拖拽手柄 const DragHandle = SortableHandle(() => ( <MenuOutlined title='拖拽排序' /> )) // 表格排序方法 const onSortEnd = ({oldIndex, newIndex}: {oldIndex: number; newIndex: number }) => { if (oldIndex !== newIndex) { const newData: any[] = arrayMoveImmutable(([] as any[]).concat(dataSource), oldIndex, newIndex).filter((el: any) => !!el); handleAllSave(newData) // 父組件傳過來(lái)的方法,用于更新表格第一列的序號(hào) } } // 所有可拖拽排序元素的容器 // DragTableContainer 是上面通過 SortableContainer 定義的拖拽的table 容器 // useDragHandle 參數(shù),意思是: 使用行把手拖拽行排序 // disableAutoscroll 參數(shù),禁止自動(dòng)滾動(dòng) // helperClass 參數(shù),可修改拖拽樣式 // onSortEnd `SortableContainer` 提供的一個(gè)方法,這個(gè)方法可以解構(gòu)兩個(gè)形參:`{ oldIndex , newIndex }`,一個(gè)是拖拽元素的標(biāo)記,一個(gè)是將要放的地方的標(biāo)記,用于表格拖拽排序 const DraggableContainer = (props: any) => <DragTableContainer useDragHandle disableAutoscroll helperClass="row-dragging" onSortEnd={onSortEnd} {...props}/> // 定義 拖拽的 行 // DraggableBodyRow 返回的是由 SortableItem 包裹的每一行元素 const DraggableBodyRow = ({ className, style, ...restProps}: any) => { const index = dataSource.findIndex((x: any) => x.orderNum === restProps['data-row-key']); return (<SortableItem index={index} {...restProps} />) } // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // 封裝的子組件 const EditableTable = (props: any) => { let { title = '', subtitle = '', columns, rowClassName = () => 'editable-row', dataSource, handleSave, handleAllSave, rowKey, placeholder, clickRow, loading = false, scroll } = props; const styles = { tabletitle: { fontWeight: 800, color: '#0095ff', fontSize: '16px' }, subtitle: { color: '#000000', fontSize: '12px' }, }; columns = columns.map((col: any) => { if (!col.editable) { return col; } return { ...col, onCell: (record: any) => ({ record, isRowDisable: col.isRowDisable, isNumber: col.isNumber, editable: col.editable, editdisable: col.editdisable, dataIndex: col.dataIndex, title: col.title, handleSave: handleSave, formRules: col.rules, placeholder: col?.placeholder, precision: col?.precision, min: col?.min, step: col?.step, max: col?.max, formatter: col?.formatter, parser: col?.parser, }), }; }); /** * 表格行屬性 * @param record 表格每行的數(shù)據(jù) * @returns */ const onRow = (record: any) => { return { onClick: clickRow ? () => clickRow(record) : undefined, } } const onSortEnd = ({oldIndex, newIndex}: {oldIndex: number; newIndex: number }) => { if (oldIndex !== newIndex) { const newData: any[] = arrayMoveImmutable(([] as any[]).concat(dataSource), oldIndex, newIndex).filter((el: any) => !!el); handleAllSave(newData) } } const DraggableContainer = (props: any) => <SortableBody useDragHandle disableAutoscroll helperClass="row-dragging" onSortEnd={onSortEnd} {...props}/> const DraggableBodyRow = ({ className, style, ...restProps}: any) => { const index = dataSource.findIndex((x: any) => x.orderNum === restProps['data-row-key']); return (<SortableItem index={index} {...restProps} />) } return ( <Fragment> <div style={{ display: 'flex', marginBottom: '6px' }}> <Table className="wrap" style={{ width: '100%' }} locale={{ emptyText: '暫無(wú)數(shù)據(jù)' }} components={{ body: { wrapper: DraggableContainer, row: DraggableBodyRow, // cell: EditableCell } }} rowClassName={rowClassName} bordered dataSource={dataSource} columns={columns} pagination={false} rowKey='orderNum' scroll={scroll || { y: 500 }} onRow={onRow} loading={loading} /> </div> </Fragment> ); }; export default memo(EditableTable);
到此這篇關(guān)于react 實(shí)現(xiàn)表格列表拖拽排序的示例的文章就介紹到這了,更多相關(guān)react 表格列表拖拽排序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- react-dnd實(shí)現(xiàn)任意拖動(dòng)與互換位置
- react-native 圓弧拖動(dòng)進(jìn)度條實(shí)現(xiàn)的示例代碼
- react項(xiàng)目中使用react-dnd實(shí)現(xiàn)列表的拖拽排序功能
- react中實(shí)現(xiàn)拖拽排序react-dnd功能
- React如何使用sortablejs實(shí)現(xiàn)拖拽排序
- React.js組件實(shí)現(xiàn)拖拽排序組件功能過程解析
- react.js組件實(shí)現(xiàn)拖拽復(fù)制和可排序的示例代碼
- react實(shí)現(xiàn)記錄拖動(dòng)排序
相關(guān)文章
詳解開發(fā)react應(yīng)用最好用的腳手架 create-react-app
本篇文章主要介紹了詳解開發(fā)react應(yīng)用最好用的腳手架 create-react-app,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2018-04-04react基于Ant Desgin Upload實(shí)現(xiàn)導(dǎo)入導(dǎo)出
本文主要介紹了react基于Ant Desgin Upload實(shí)現(xiàn)導(dǎo)入導(dǎo)出,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01React?中如何將CSS?visibility?屬性設(shè)置為?hidden
這篇文章主要介紹了React中如何將CSS?visibility屬性設(shè)置為?hidden,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05使用React hook實(shí)現(xiàn)remember me功能
相信大家在使用 React 寫頁(yè)面的時(shí)候都遇到過完成 Remember me 的需求吧!本文就將這個(gè)需求封裝在一個(gè) React hook 中以供后續(xù)的使用,覺得有用的同學(xué)可以收藏起來(lái)以備不時(shí)之需,感興趣的小伙伴跟著小編一起來(lái)看看吧2024-04-04React報(bào)錯(cuò)之Parameter event implicitly has a
這篇文章主要為大家介紹了React報(bào)錯(cuò)之Parameter event implicitly has an any type,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08React利用路由實(shí)現(xiàn)登錄界面的跳轉(zhuǎn)
這篇文章主要介紹了React利用路由實(shí)現(xiàn)登錄界面的跳轉(zhuǎn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04React Native按鈕Touchable系列組件使用教程示例
這篇文章主要為大家介紹了React Native按鈕Touchable系列組件使用教程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11