--- order: 13 title: zh-CN: 可拖拽标签 en-US: Draggable Tabs --- ## zh-CN 使用 `react-dnd@15+` 实现标签可拖拽。 ## en-US Use `react-dnd@15+` to make tabs draggable. ```tsx import type { TabsProps } from 'antd'; import { Tabs } from 'antd'; import React, { useRef, useState } from 'react'; import { DndProvider, useDrag, useDrop } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; const type = 'DraggableTabNode'; interface DraggableTabPaneProps extends React.HTMLAttributes { index: React.Key; moveNode: (dragIndex: React.Key, hoverIndex: React.Key) => void; } const DraggableTabNode = ({ index, children, moveNode }: DraggableTabPaneProps) => { const ref = useRef(null); const [{ isOver, dropClassName }, drop] = useDrop({ accept: type, collect: monitor => { const { index: dragIndex } = monitor.getItem() || {}; if (dragIndex === index) { return {}; } return { isOver: monitor.isOver(), dropClassName: 'dropping', }; }, drop: (item: { index: React.Key }) => { moveNode(item.index, index); }, }); const [, drag] = useDrag({ type, item: { index }, collect: monitor => ({ isDragging: monitor.isDragging(), }), }); drop(drag(ref)); return (
{children}
); }; const DraggableTabs: React.FC = props => { const { items = [] } = props; const [order, setOrder] = useState([]); const moveTabNode = (dragKey: React.Key, hoverKey: React.Key) => { const newOrder = order.slice(); items.forEach(item => { if (item.key && newOrder.indexOf(item.key) === -1) { newOrder.push(item.key); } }); const dragIndex = newOrder.indexOf(dragKey); const hoverIndex = newOrder.indexOf(hoverKey); newOrder.splice(dragIndex, 1); newOrder.splice(hoverIndex, 0, dragKey); setOrder(newOrder); }; const renderTabBar: TabsProps['renderTabBar'] = (tabBarProps, DefaultTabBar) => ( {node => ( {node} )} ); const orderItems = [...items].sort((a, b) => { const orderA = order.indexOf(a.key!); const orderB = order.indexOf(b.key!); if (orderA !== -1 && orderB !== -1) { return orderA - orderB; } if (orderA !== -1) { return -1; } if (orderB !== -1) { return 1; } const ia = items.indexOf(a); const ib = items.indexOf(b); return ia - ib; }); return ( ); }; const App: React.FC = () => ( { const id = String(i + 1); return { label: `tab ${id}`, key: id, children: `Content of Tab Pane ${id}`, }; })} /> ); export default App; ``` ```css .dropping { background: #fefefe; transition: all 0.3s; } ```