dnd 咻咻咻"/>
dnd 咻咻咻
# 1. 钩子函数APIuseDrag 拖拽
useDrop 放置
useDragLayer 拖拽层
# Drag 拖拽import {useDrag} from 'react-dnd'function Drag() {const [{isDragging}, drag, dragPreview] = useDrag(() => ({// 必须,标识可拖动组件类型type: 'BOX',// 可选,对象或者函数,获取拖动源信息或者拖动触发事件item: '',// 可选,描述拖动预览previewOptions: '',// 可选,放置是移动还是复制options: 'dropEffect',// 可选,参数(monitor/props),收集器collect: (monitor) => ({// 可选,拖动停止触发事件// end(item, monitor)// 可选,是否允许拖动// canDrag(monitor)// 可选,判断是否被拖拽// isDragging(monitor),isDragging: monitor.isDragging()})}))return (<div ref={dragPreview} style={{opacity: isDragging ? 0.5 : 1}}><div role="Handle" ref={drag}/></div>)
}
# Drop 放置import {useDrop} from 'react-dnd'function Drop() {const [{ canDrop, isOver }, drop] = useDrop(() => ({// 必须,标识可拖动组件类型accept: 'BOX',// 可选,放置触发事件// drop(item, monitor)// 可选,当项目悬停在组件上触发事件// hover(item, monitor)// 可选,是否接受放置源// canDrop(item, monitor)// 可选,参数(monitor/props),收集器collect: (monitor) => ({isOver: monitor.isOver(),canDrop: monitor.canDrop()})}))return (<divref={drop}role={'Dustbin'}style={{ backgroundColor: isOver ? 'red' : 'white' }}>{canDrop ? 'Release to drop' : 'Drag a box here'}</div>)
}
# DragLayer 拖动层import { useDragLayer } from 'react-dnd'function DragLayer(props) {const collectedProps = useDragLayer(monitor => ({isOver: monitor.isOver(),canDrop: monitor.canDrop()}))return <div>...</div>
}
# 2. 装饰器API高阶函数:高阶组件是一个函数,它接受一个 React 组件类,并返回另一个 React 组件类
# source 拖动源import React from 'react'
import { DragSource } from 'react-dnd'const Types = {CARD: 'card'
}
// 指定拖动源配置
const cardSource = {// 可选,当前是否允许拖拽canDrag(props) {return props.isReady},// 可选,isDragging(props, monitor) {return monitor.getItem().id === props.id},// 必须,拖动开始触发事件beginDrag(props, monitor, component) {const item = { id: props.id }return item},// 可选,拖动停止触发事件endDrag(props, monitor, component) {// 检查放置是否成功if (!monitor.didDrop()) {return}// 获取拖拽源数据const item = monitor.getItem()// 获取放置结果const dropResult = monitor.getDropResult()CardActions.moveCardToList(item.id, dropResult.listId)}
}
// 指定要注入组件的道具
function collect(connect, monitor) {return {connectDragSource: connect.dragSource(),// 向监视器询问当前拖动状态isDragging: monitor.isDragging()}
}
class Card {render() {const { id } = this.propsconst { isDragging, connectDragSource } = this.propsreturn connectDragSource(<div>I am a draggable card number {id}{isDragging && ' (and I am being dragged now)'}</div>)}
}
export default DragSource(Types.CARD, cardSource, collect)(Card)
# target 放置目标import React from 'react'
import { findDOMNode } from 'react-dom'
import { DropTarget } from 'react-dnd'const Types = {CHESSPIECE: 'chesspiece'
}
const chessSquareTarget = {// 是否可放置canDrop(props, monitor) {const item = monitor.getItem()return canMakeChessMove(item.fromPosition, props.position)},// 可选,组件悬停事件hover(props, monitor, component) {const clientOffset = monitor.getClientOffset()const componentRect = findDOMNode(component).getBoundingClientRect()const isOnlyThisOne = monitor.isOver({ shallow: true })const canDrop = monitor.canDrop()},// 可选,放置触发事件drop(props, monitor, component) {if (monitor.didDrop()) {return}const item = monitor.getItem()ChessActions.movePiece(item.fromPosition, props.position)return { moved: true }}
}
function collect(connect, monitor) {return {connectDropTarget: connect.dropTarget(),isOver: monitor.isOver(),isOverCurrent: monitor.isOver({ shallow: true }),canDrop: monitor.canDrop(),itemType: monitor.getItemType()}
}
class ChessSquare {componentDidUpdate(prevProps) {if (!prevProps.isOver && this.props.isOver) {}if (prevProps.isOver && !this.props.isOver) {}if (prevProps.isOverCurrent && !this.props.isOverCurrent) {}}render() {const { position } = this.propsconst { isOver, canDrop, connectDropTarget } = this.propsreturn connectDropTarget(<div className="Cell">{isOver && canDrop && <div class="green" />}{!isOver && canDrop && <div class="yellow" />}{isOver && !canDrop && <div class="red" />}</div>)}
}
export default DropTarget(Types.CHESSPIECE,chessSquareTarget,collect
)(ChessSquare)
# 拖拽层import React from 'react'
import ItemTypes from './ItemTypes'
import BoxDragPreview from './BoxDragPreview'
import snapToGrid from './snapToGrid'
import { DragLayer } from 'react-dnd'const layerStyles = {position: 'fixed',pointerEvents: 'none',zIndex: 100,left: 0,top: 0,width: '100%',height: '100%'
}
function getItemStyles(props) {const { currentOffset } = propsif (!currentOffset) {return {display: 'none'}}const { x, y } = currentOffsetconst transform = `translate(${x}px, ${y}px)`return {transform: transform,WebkitTransform: transform}
}
function CustomDragLayer({ item, itemType, isDragging }) {if (!isDragging) {return null}function renderItem(type, item) {switch (type) {case ItemTypes.BOX:return <BoxDragPreview title={item.title} />}}return (<div style={layerStyles}><div style={getItemStyles(props)}>{renderItem(itemType, item)}</div></div>)
}
function collect(monitor) {return {item: monitor.getItem(),itemType: monitor.getItemType(),currentOffset: monitor.getSourceClientOffset(),isDragging: monitor.isDragging()}
}export default DragLayer(collect)(CustomDragLayer)
更多推荐
dnd 咻咻咻
发布评论