我正在尝试在 react-virtualized 中设置 react-dnd 可排序列表List
。我正在使用 react-dnd 的示例在这里:
https://react-dnd.github.io/react-dnd/examples-sortable-simple.html
我已经让它大部分工作了,但是当我拖动一个项目时,我悬停的项目不会调整它们的不透明度并正确重新排序。
我制作了一个示例项目来演示该问题(https://github.com/ericdcobb/virtual-drag-n-drop),但会将代码粘贴到此处。这是 DragDropContext:
import React, {Component} from 'react';
import './App.css';
import {List} from 'react-virtualized';
import {name} from 'faker';
import Item from './Item.js';
import {DragDropContext} from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import update from 'react/lib/update';
class App extends Component {
constructor(props) {
super(props);
const items = [];
for (let i = 0; i < 1000; i += 1) {
const item = {
id: i,
text: name.findName()
};
items[i] = item;
}
this.state = {
items: items
}
this.rowRenderer = this.rowRenderer.bind(this);
this.moveItem = this.moveItem.bind(this);
}
moveItem(dragIndex, hoverIndex) {
const {items} = this.state;
const dragItem = items[dragIndex];
this.setState(update(this.state, {
items: {
$splice: [
[
dragIndex, 1
],
[hoverIndex, 0, dragItem]
]
}
}));
}
rowRenderer(row) {
const {items} = this.state;
const item = items[row.index]
return (<Item index={row.index} key={row.key} style={row.style} item={item} moveItem={this.moveItem}/>);
}
render() {
const {items} = this.state;
return (
<div className="App">
<List className="list-group" width={800} items={items} height={1000} rowCount={items.length} rowHeight={55} rowRenderer={this.rowRenderer}/>
</div>
);
}
}
export default DragDropContext(HTML5Backend)(App);
和 DragSource/DragTarget:
import React, {Component} from 'react';
import {DragSource, DropTarget} from 'react-dnd';
import { findDOMNode } from 'react-dom';
import _ from 'lodash';
const ItemSource = {
beginDrag(props) {
return {id: props.item.id,
index: props.index};
}
};
const ItemTarget = {
hover(props, monitor, component) {
const dragIndex = monitor.getItem().index;
const hoverIndex = props.index;
// Don't replace items with themselves
if (dragIndex === hoverIndex) {
return;
}
// Determine rectangle on screen
const hoverBoundingRect = findDOMNode(component).getBoundingClientRect();
// Get vertical middle
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
// Determine mouse position
const clientOffset = monitor.getClientOffset();
// Get pixels to the top
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
// Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50%
// Dragging downwards
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return;
}
// Dragging upwards
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return;
}
// Time to actually perform the action
props.moveItem(dragIndex, hoverIndex);
// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
monitor.getItem().index = hoverIndex;
}
};
function collect(connect, monitor) {
return {connectDragSource: connect.dragSource(), isDragging: monitor.isDragging()}
}
function connect(connect, monitor) {
return {connectDropTarget: connect.dropTarget()}
}
class Item extends Component {
render() {
let self = this;
const {connectDragSource, isDragging, connectDropTarget, style} = self.props;
const opacity = isDragging
? 0
: 1;
return connectDragSource(connectDropTarget(
<div key={self.props.key} style={{...style, opacity}} className="Item">
<div className="row">
<div className="col-md-10">{self.props.item.text}</div>
</div>
</div>
));
}
}
//TODO constant for this first string
export default _.flow([
DragSource('item', ItemSource, collect),
DropTarget('item', ItemTarget, connect)
])(Item);
我试图让项目在拖动的项目周围流动,就像在示例中所做的那样。似乎在我的实现中,错误的项目变得不透明,并且无法向上或向下移动。
抱歉这里有些含糊不清,我想在屏幕上拖放东西很难说,希望代码和屏幕截图有助于解释我的问题。
谢谢!