mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-16 01:41:02 +08:00
154 lines
3.1 KiB
Markdown
154 lines
3.1 KiB
Markdown
---
|
|
order: 13
|
|
title:
|
|
zh-CN: 可拖拽标签
|
|
en-US: Draggable Tabs
|
|
---
|
|
|
|
## zh-CN
|
|
|
|
使用 `react-dnd` 实现标签可拖拽。
|
|
|
|
## en-US
|
|
|
|
Use `react-dnd` to make tabs draggable.
|
|
|
|
```jsx
|
|
import { Tabs } from 'antd';
|
|
import { DndProvider, DragSource, DropTarget } from 'react-dnd';
|
|
import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
|
|
const { TabPane } = Tabs;
|
|
|
|
// Drag & Drop node
|
|
class TabNode extends React.Component {
|
|
render() {
|
|
const { connectDragSource, connectDropTarget, children } = this.props;
|
|
|
|
return connectDragSource(connectDropTarget(children));
|
|
}
|
|
}
|
|
|
|
const cardTarget = {
|
|
drop(props, monitor) {
|
|
const dragKey = monitor.getItem().index;
|
|
const hoverKey = props.index;
|
|
|
|
if (dragKey === hoverKey) {
|
|
return;
|
|
}
|
|
|
|
props.moveTabNode(dragKey, hoverKey);
|
|
monitor.getItem().index = hoverKey;
|
|
},
|
|
};
|
|
|
|
const cardSource = {
|
|
beginDrag(props) {
|
|
return {
|
|
id: props.id,
|
|
index: props.index,
|
|
};
|
|
},
|
|
};
|
|
|
|
const WrapTabNode = DropTarget('DND_NODE', cardTarget, connect => ({
|
|
connectDropTarget: connect.dropTarget(),
|
|
}))(
|
|
DragSource('DND_NODE', cardSource, (connect, monitor) => ({
|
|
connectDragSource: connect.dragSource(),
|
|
isDragging: monitor.isDragging(),
|
|
}))(TabNode),
|
|
);
|
|
|
|
class DraggableTabs extends React.Component {
|
|
state = {
|
|
order: [],
|
|
};
|
|
|
|
moveTabNode = (dragKey, hoverKey) => {
|
|
const newOrder = this.state.order.slice();
|
|
const { children } = this.props;
|
|
|
|
React.Children.forEach(children, c => {
|
|
if (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);
|
|
|
|
this.setState({
|
|
order: newOrder,
|
|
});
|
|
};
|
|
|
|
renderTabBar = (props, DefaultTabBar) => (
|
|
<DefaultTabBar {...props}>
|
|
{node => (
|
|
<WrapTabNode key={node.key} index={node.key} moveTabNode={this.moveTabNode}>
|
|
{node}
|
|
</WrapTabNode>
|
|
)}
|
|
</DefaultTabBar>
|
|
);
|
|
|
|
render() {
|
|
const { order } = this.state;
|
|
const { children } = this.props;
|
|
|
|
const tabs = [];
|
|
React.Children.forEach(children, c => {
|
|
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 (
|
|
<DndProvider backend={HTML5Backend}>
|
|
<Tabs renderTabBar={this.renderTabBar} {...this.props}>
|
|
{orderTabs}
|
|
</Tabs>
|
|
</DndProvider>
|
|
);
|
|
}
|
|
}
|
|
|
|
ReactDOM.render(
|
|
<DraggableTabs>
|
|
<TabPane tab="tab 1" key="1">
|
|
Content of Tab Pane 1
|
|
</TabPane>
|
|
<TabPane tab="tab 2" key="2">
|
|
Content of Tab Pane 2
|
|
</TabPane>
|
|
<TabPane tab="tab 3" key="3">
|
|
Content of Tab Pane 3
|
|
</TabPane>
|
|
</DraggableTabs>,
|
|
mountNode,
|
|
);
|
|
```
|