--- 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 { TabPane } = Tabs; 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<{ children: React.ReactNode }> = props => { const { children } = props; const [order, setOrder] = useState([]); const moveTabNode = (dragKey: React.Key, hoverKey: React.Key) => { const newOrder = order.slice(); React.Children.forEach(children, (c: React.ReactElement) => { if (c.key && newOrder.indexOf(c.key) === -1) { newOrder.push(c.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 tabs: React.ReactElement[] = []; React.Children.forEach(children, (c: React.ReactElement) => { tabs.push(c); }); const orderTabs = tabs.slice().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 = tabs.indexOf(a); const ib = tabs.indexOf(b); return ia - ib; }); return ( {orderTabs} ); }; const App: React.FC = () => ( Content of Tab Pane 1 Content of Tab Pane 2 Content of Tab Pane 3 ); export default App; ``` ```css .dropping { background: #fefefe; transition: all 0.3s; } ```