You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

168 lines
3.2 KiB

---
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);
````