mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-03 00:09:39 +08:00
168 lines
3.2 KiB
Markdown
168 lines
3.2 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 { DragDropContextProvider, DragSource, DropTarget } from 'react-dnd';
|
||
|
import HTML5Backend from 'react-dnd-html5-backend';
|
||
|
|
||
|
const TabPane = Tabs.TabPane;
|
||
|
|
||
|
// 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 (
|
||
|
<DragDropContextProvider backend={HTML5Backend}>
|
||
|
<Tabs
|
||
|
renderTabBar={this.renderTabBar}
|
||
|
{...this.props}
|
||
|
>
|
||
|
{orderTabs}
|
||
|
</Tabs>
|
||
|
</DragDropContextProvider>
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
````
|