我想实现一个drop系统,如果drop目标是嵌套的,你可以使用鼠标滚轮在它们之间循环(或者在一定时间后发生自动循环)这将特别有用,因为许多嵌套目标在屏幕上占据完全相同的区域。
我目前正在考虑我可以使用从容器传下来的回调,当调用悬停函数/当isOver prop更改时它可以被drop目标用来注册/取消注册,但它&#39 ; s非常耦合,我必须从容器传递道具到DropTargets,在现实世界的应用程序中,容器和放置目标之间将有未知数量的级别,所以我可能不得不设置某种回调系统,整体而言不是理想的解决方案。此外,我不确定如何在骑行时确保正确的顺序,因为放置目标不知道它们的嵌套程度如何(请参阅下面的代码,了解我是如何实现这一点的)。有没有更简洁的方法来实现这样的系统?
@DragDropContext(HTML5Backend)
export default class Container extends Component {
constructor (props) {
super(props);
this.state = {
bins: []
};
this.status = {};
this._cycle = this.cycle.bind(this);
this._register = this.register.bind(this);
this._deregister = this.deregister.bind(this);
}
componentWillUnmount () {
if (this.timer) {
window.clearInterval(this.timer);
}
}
register (name) {
if (this.state.bins.findIndex(e => e === name) === -1) {
this.setState({
bins: this.state.bins.concat(name)
});
if (!this.timer) {
this.cycledBins = [];
this.timer = window.setInterval(this._cycle, 3000);
this._cycle();
}
}
}
deregister (name) {
if (this.state.bins.findIndex(e => e === name) !== -1) {
const bins = this.state.bins.filter((e) => e === name);
this.setState({
bins
});
if (!bins.length) {
window.clearInterval(this.timer);
this.timer = undefined;
}
}
}
cycle () {
this.status = {};
const bins = this.state.bins;
let activeBin = -1;
for (let i = 0; i < bins.length; i += 1) {
if (this.cycledBins.findIndex(bin => bin === bins[i]) === -1) {
activeBin = bins[i];
break;
}
}
if (activeBin === -1) {
activeBin = bins[0];
this.cycledBins = [];
}
this.cycledBins.push(activeBin);
this.activeBin = activeBin;
this.status[activeBin] = {
isActive: true,
isOnlyActive: bins.length === 1
}
this.forceUpdate();
}
render () {
return (
<div>
bins = {JSON.stringify(this.state.bins)}<br />
cycledBins = {JSON.stringify(this.cycledBins)}
<div style={{ overflow: 'hidden', clear: 'both' }}>
<Dustbin name="Outer" register={this._register} deregister={this._deregister} status={this.status["Outer"]} >
<Dustbin name="Middle" register={this._register} deregister={this._deregister} status={this.status["Middle"]} >
<Dustbin name="Inner" register={this._register} deregister={this._deregister} status={this.status["Inner"]} />
</Dustbin>
</Dustbin>
</div>
<div style={{ overflow: 'hidden', clear: 'both' }}>
<Box name='Glass' />
<Box name='Banana' />
<Box name='Paper' />
</div>
</div>
);
}
}
const boxTarget = {
hover(props) {
props.register(props.name);
}
};
@DNDDropTarget('Box', boxTarget, (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver()//,
//canDrop: monitor.canDrop()
}))
export default class Dustbin extends Component {
static propTypes = {
connectDropTarget: PropTypes.func.isRequired,
isOver: PropTypes.bool.isRequired//,
//canDrop: PropTypes.bool.isRequired
};
componentWIllMount () {
if (!this.props.isOver) {
this.props.deregister(this.props.name);
}
}
componentWillReceiveProps (nextProps) {
if (nextProps.isOver !== this.props.isOver && !nextProps.isOver) {
this.props.deregister(this.props.name);
}
}
render() {
const { canDrop, isOver, connectDropTarget, status } = this.props;
const isOnlyActive = status && status.isOnlyActive;
let isActive = status && status.isActive;
if (!isOver && isActive) {
isActive = false;
}
return connectDropTarget(
<div>
<DropTarget position={BEFORE} shown={isActive} />
{ isActive && !isOnlyActive ? '(' + this.props.name + ')' : undefined }
{ this.props.children ? this.props.children : (
<div style={style}>
{ isActive ?
'Release to drop' :
'Drag a box here'
}
</div>
) }
<DropTarget position={AFTER} shown={isActive} />
</div>
);
}
}