daily-share icon indicating copy to clipboard operation
daily-share copied to clipboard

react-beautiful-dnd 初探(2020-11-4)

Open yaogengzhu opened this issue 4 years ago • 1 comments

简单的使用方式

  • hooks 方式实现
import React, { useState } from 'react'
import { DragDropContext, Droppable, Draggable, DropResult, DraggingStyle } from "react-beautiful-dnd"
import {  createUseStyles } from 'react-jss'

const styles = createUseStyles({
    box: {
        width: '100%',
        height: '100px',
    }
})

export const Demo: React.FC = () => {
    const classes = styles()

    const getItems = (count: number) => {
        return Array.from({ length: count }, (v, k) => k).map(k => ({
            id: `item-${k}`,
            content: `item ${k}`
          }))
    }

    const [items, setItems] = useState(getItems(4))
    const onDragEnd = (res: DropResult) => {
        if (!res.destination) {
            return
        }
        const item = reorder(items, res.source.index, res.destination.index)
        setItems([...item])
    }

    const reorder = (list: any, startIndex: number, endIndex: number) => {
        console.log(endIndex, startIndex)
        const result = list
        const [removed] = result.splice(startIndex, 1)
        result.splice(endIndex, 0, removed)

        return result
    }

    // 样式相关
    const getListStyle = (isDraggingOver: boolean) => ({
        background: isDraggingOver ? "lightblue" : "lightgrey"
    })

    // 样式相关
    const getItemStyle = (isDragging: boolean, draggableStyle: any) => ({
        userSelect: "none",
        // change background colour if dragging
        background: isDragging ? "lightgreen" : "grey",
        // styles we need to apply on draggables
        ...draggableStyle
      })

    return (
        <DragDropContext onDragEnd={onDragEnd}>
            <Droppable droppableId="droppable">
                {(provided, snapshot) => (
                    <div
                        {...provided.droppableProps}
                        ref={provided.innerRef}
                        style={{
                            height: '600px',
                            width: '100%',
                            ...getListStyle(snapshot.isDraggingOver)
                        }}
                    >
                        {
                            items.map( (item, index) => (
                                <Draggable key={item.id} draggableId={item.id} index={index}>
                                    {(provided1, snapshot1) => (
                                        <div
                                            ref={provided1.innerRef}
                                            {...provided1.draggableProps}
                                            {...provided1.dragHandleProps}
                                            className={ classes. box}
                                            style={{ ...getItemStyle(snapshot1.isDragging, provided1.draggableProps.style), animation: snapshot1.dropAnimation}}
                                        >{ item.content }
                                        </div>
                                    )}
                                </Draggable>
                            ))
                        }
                    </div>
                )}
            </Droppable>
        </DragDropContext>
    )
}

yaogengzhu avatar Nov 04 '20 11:11 yaogengzhu

实战组件封装


import React, { useState } from 'react'
import { DragDropContext, Droppable, Draggable, DropResult, DraggingStyle } from "react-beautiful-dnd"
import {  createUseStyles } from 'react-jss'
import { Iconfont } from '../icon-font/icon-font'
import { Row } from '../layout/base'

const styles = createUseStyles({
    item: {
        position: 'relative',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'space-between',
        height: '50px',
        backgroundColor: '#fff',

        "&:after": {
            position: 'absolute',
            bottom: 0,
            width: 'calc(100% - 20px)',
            content: "''",
            margin: '0 10px',
            height: '1px',
            backgroundColor: 'rgba(0, 0, 0, 0.05)'
        }
    },
    left: {
        display: 'flex',
        alignItems: 'center',
        flex: 1,
        height: '50px',
        paddingLeft: '10px',
        flexShrink: 0
    },
    right: {
        position: 'relative',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        width: '60px',
        height: '50px',

        "&:after": {
            left: 0,
            position: 'absolute',
            content: "''",
            width: '1px',
            height: '20px',
            backgroundColor: 'rgba(0, 0, 0, 0.1)'
        }
    }
})

interface IProps {
    lists?: Array<{
        [x: string]: any,
        id: number,
        title: string
    }>
}

export const DragDrop: React.FC<IProps> = (props) => {
    const classes = styles()
    const { lists } = props

    const [items, setItems] = useState(lists)
    const onDragEnd = (res: DropResult) => {
        if (!res.destination) {
            return
        }
        const item = reorder(items, res.source.index, res.destination.index)
        setItems([...item])
    }

    const reorder = (list: any, startIndex: number, endIndex: number) => {
        console.log(endIndex, startIndex)
        const result = list
        const [removed] = result.splice(startIndex, 1)
        result.splice(endIndex, 0, removed)

        return result
    }

    // 样式相关
    const getListStyle = (isDraggingOver: boolean) => ({
        background: '#fff'
    })

    // 样式相关
    const getItemStyle = (isDragging: boolean, draggableStyle: any) => ({
        userSelect: "none",
        boxShadow: isDragging ? '1px 3px 5px rgb(0 0 0 / 10%)' : '',
        ...draggableStyle
      })

    return (
        <DragDropContext onDragEnd={onDragEnd}>
            <Droppable droppableId="droppable">
                {(provided, snapshot) => (
                    <div
                        {...provided.droppableProps}
                        ref={provided.innerRef}
                        style={{
                            width: '100%',
                            ...getListStyle(snapshot.isDraggingOver)
                        }}
                    >
                        {
                            items && items.map( (item, index) => (
                                <Draggable
                                    key={item.id} draggableId={item.title} index={index}
                                >
                                    {(provided1, snapshot1) => (
                                        <div
                                            ref={provided1.innerRef}
                                            className={ classes.item }
                                            {...provided1.draggableProps}
                                            style={{ ...getItemStyle(snapshot1.isDragging, provided1.draggableProps.style), animation: snapshot1.dropAnimation}}
                                        >
                                                <Row className={ classes.left }>
                                                    <span>{ item.title }</span>
                                                </Row>
                                                <div
                                                    className={ classes.right }
                                                    {...provided1.dragHandleProps}
                                                >
                                                    <Iconfont name='icontuodong' size='25'></Iconfont>
                                                </div>
                                        </div>
                                    )}
                                </Draggable>
                            ))
                        }
                    </div>
                )}
            </Droppable>
        </DragDropContext>
    )
}
DragDrop.defaultProps = {
    lists: [
        {
            id: 1,
            title: '列表1'
        },
        {
            id: 2,
            title: '列表2'
        },
        {
            id: 3,
            title: '列表3'
        }
    ]
}

展示

image

yaogengzhu avatar Mar 17 '21 10:03 yaogengzhu