美文网首页
react-dnd-拖拽排序

react-dnd-拖拽排序

作者: skoll | 来源:发表于2020-08-28 21:18 被阅读0次

DropTargetMonitor

1 .getClientOffset()

1 .返回{ x, y }正在进行拖动操作时指针的最后记录的客户端偏移量。null如果没有项目被拖动,则返回
2 .客户端就是父元素的顶部的位移距离。如果从最上面往下拖拽,那么y值是越来越大的,如果是从最下面往上拖拽,那么y值是越来越小的。所有的位置是相对与左上角的
3 .时时刻刻都会变化的

2 .getInitialClientOffset:

1 .返回{ x, y }当前拖动操作开始时指针的客户端偏移量。null如果没有项目被拖动,则返回
2 .

3 .getInitialSourceClientOffset()

1 .返回{ x, y }当前拖动操作开始时拖动源组件的根DOM节点的客户端偏移量。null如果没有项目被拖动,则返回
2 .没看出和上面的有什么不一样

4 .getSourceClientOffset()

1 .和第一个差不多
2 .{ x, y }根据当前拖动操作开始时的位置以及移动差异,返回拖动源组件的根DOM节点的预计客户端偏移量。null如果没有项目被拖动,则返回

5 .getDifferenceFromInitialOffset()

1 .返回{ x, y }当前拖动操作开始时指针的最后记录的客户端偏移量与客户端偏移量之间的差。null如果没有项目被拖动,则返回
2 .和第一个差不多,只不过从上到下是正值,从下到上是负值

cards.tsx

import React,{useRef} from 'react'
import {useDrop,useDrag, DropTargetMonitor, XYCoord} from 'react-dnd'

const style={
    border:'1px dashed gray',
    padding:'0.5rem 1rem',
    marginBottom:'.5rem',
    backgroundBolor:"white",
    cursor:"move",
    transition:"all 0.3s"
}
interface CardOptions{
    id:number,
    text:string,
    index:number,
    moveCard:(dragIndex:number,hoverIndex:number)=>void,
}

interface DragItem{
    index:number,
    id:string,
    type:string,
}

export default function Card({id,text,index,moveCard}:CardOptions){
    const ref=useRef<HTMLDivElement>(null)
    const [{isDragging},drag]=useDrag({
        item:{type:"Card",id,index},
        collect:(mointor:any)=>({
            isDragging:mointor.isDragging()
        })
    })

    const [,drop]=useDrop({
        accept:"Card",
        hover:(item:DragItem,mointor:DropTargetMonitor)=>{
            // 这里必须加上DragItem这个范围限制,不然访问不到属性
            // console.log('dragIndex',item.index)

            if(!ref.current){
                return
            }

            const dragIndex=item.index
            const hoverIndex=index
             if(dragIndex===hoverIndex){
                return 
            }

            const hoverBoundingRect=ref.current?.getBoundingClientRect()
            if(hoverBoundingRect){
                const hoverMiddleY=(hoverBoundingRect.bottom-hoverBoundingRect.top)/2
                const clientOffSet=mointor.getClientOffset()
                const hoverClientY=(clientOffSet as XYCoord).y-hoverBoundingRect.top

                if(dragIndex<hoverIndex&&hoverClientY<hoverMiddleY){
                    return 
                }

                if(dragIndex>hoverIndex&&hoverClientY>hoverMiddleY){
                    return 
                }

                moveCard(dragIndex,hoverIndex)
                item.index=hoverIndex
            }
        }
    })

    const opacity=isDragging?0:1
    drag(drop(ref))
    return(
        <div 
            ref={ref}
            style={{...style,opacity}}
        >
            {text}
        </div>
    ) 
}

container.tsx

import React,{useState,useCallback} from 'react'
import {Dustin} from './Dustbin'
import Box from './box'
import Card from './card'
import update from 'immutability-helper'
const style={
    width:400,
    margin:100,
}

export default function Container(){
    const [cards,setCards]=useState([
        {
            id: 1,
            text: 'Write a cool JS library',
          },
          {
            id: 2,
            text: 'Make it generic enough',
          },
          {
            id: 3,
            text: 'Write README',
          },
          {
            id: 4,
            text: 'Create some examples',
          },
          {
            id: 5,
            text:
              'Spam in Twitter and IRC to promote it (note that this element is taller than the others)',
          },
          {
            id: 6,
            text: '???',
          },
          {
            id: 7,
            text: 'PROFIT',
          },
    ])

    const moveCard=useCallback((dragIndex:number,hoverIndex:number)=>{
        // 把拖拽的元素的索引和鼠标悬浮的索引交换
        const dragCard=cards[dragIndex]
        setCards(update(cards,{
            $splice:[
                [dragIndex,1],
                // 删除
                [hoverIndex,0,dragCard]
                // 添加
                // 好像是个链式操作
            ]
        }))
    },[cards])
    // 这个方法可以被传递到子组件里面,还有定义在父组件的card数据,也可以被子组件通过这个函数给修改
    

    const renderCard=(card:{id:number,text:string},index:number)=>{
        return (
            <Card
                key={card.id}
                index={index}
                id={card.id}
                text={card.text}
                moveCard={moveCard}
            />
        )
    }
    return (
      <>
        <div style={style}>
           {cards.map((card,i)=>(
             renderCard(card,i)
           ))}
        </div>
      </>
    )
}

相关文章

网友评论

      本文标题:react-dnd-拖拽排序

      本文链接:https://www.haomeiwen.com/subject/warcsktx.html