在没风的地方找太阳  在你冷的地方做暖阳 人事纷纷  你总太天真  往后的余生  我只要你 往后余生  风雪是你  平淡是你  清贫也是你 荣华是你  心底温柔是你  目光所致  也是你 想带你去看晴空万里  想大声告诉你我为你着迷 往事匆匆  你总会被感动  往后的余生  我只要你 往后余生  冬雪是你  春花是你  夏雨也是你 秋黄是你  四季冷暖是你  目光所致  也是你 往后余生  风雪是你  平淡是你  清贫也是你 荣华是你  心底温柔是你  目光所致  也是你
jQuery火箭图标返回顶部代码 - 站长素材

使用react 实现拖拽功能

一、关于拖动

图片默认可以拖动,其他元素的拖动效果同图片。正常的 div 是不能被拖动的,鼠标点击选择后移动没有效果,需要加 draggable="true" 使得元素可以被拖动。

二、拖拽相关的几个事件

被拖拽元素的事件:ondragstart,ondragend 

放置元素的事件:ondragenter、ondragover、ondragleave、ondrop 

顾名思义,不需要解释。

需要注意是 ondragover 的默认事件 Reset the current drag operation to "none". 所以想让一个元素可放置,需要重写 ondragover 

element.ondragover = event => { 
    event.preventDefault();
    // ...
}

当一个元素是可放置的,拖拽经过时鼠标会变成加号(cursor: copy;)

 有一个对象 dataTransfer 可以用来存储拖拽数据。

dragEle.ondragstart = e => e.dataTransfer.setData('item', e.target.id);

拖拽开始时触发,把被拖拽元素的 id 存入  e.dataTransfer 

然后在 ondrop 的时候 可以获取到这个值 (ondragenter、ondragover、ondragleave 获取不到...)

putEle.ondrop = function(e) {
     let id = e.dataTransfer.getData('item');
     // ...
}

 三、react中使用代码演示 [点击查看演示]

 

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
        <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
        <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
        <style>
            .item {
                border: 1px solid #1da921;
                width: 180px;
                border-radius: 5px;
                box-shadow: 0 0 5px 0 #b3b3b3;
                margin: 5px auto;
                background: #fff;
            }
            .item.active {
                border-style: dashed;
            }
            .item-header {
                font-size: 12px;
                color: #9e9e9e;
                padding: 3px 5px;
            }
            .item-main {
                padding: 5px;
                font-size: 14px;
                color: #424242;
                height: 36px;
                overflow: hidden;
                text-overflow: ellipsis;
                display: -webkit-box;
                -webkit-box-orient: vertical;
                -webkit-line-clamp: 2;
            }
            .item-header-point {
                background: #ccc;
                float: right;
                padding: 0 4px;
                min-width: 10px;
                text-align: center;
                color: #fff;
                border-radius: 50%;
            }
            .col {
                border: 1px solid #d2d2d2;
                flex-grow: 1;
                width: 180px;
                height: 100%;
                margin: 0 2px;
                background: #eee;
                flex-grow: 1;
                display: flex;
                flex-direction: column;
            }
            .col-header {
                height: 40px;
                line-height: 40px;
                background: #1DA921;
                color: #fff;
                text-align: center;
            }
            .col-main {
                overflow: auto;
                flex-grow: 1;
            }
            .col-main.active {
                background: #00ad23;
                opacity: 0.1;
            }
            .task-wrapper {
                display: flex;
                height: 400px;
                width: 700px;
            }
        </style>
    </head>
    <body>
        <div id="app"></div>
        <script type="text/babel">
            const STATUS_TODO = 'STATUS_TODO';
            const STATUS_DOING = 'STATUS_DOING';
            const STATUS_DONE = 'STATUS_DONE';
            
            const STATUS_CODE = {
                STATUS_TODO: '待处理',
                STATUS_DOING: '进行中',
                STATUS_DONE: '已完成'
            }
            let tasks = [{
                id: 0,
                status: STATUS_TODO,
                title: '每周七天阅读五次,每次阅读完要做100字的读书笔记',
                username: '小夏',
                point: 10
            }, {
                id: 1,
                status: STATUS_TODO,
                title: '每周七天健身4次,每次健身时间需要大于20分钟',
                username: '橘子🍊',
                point: 5
            }, {
                id: 2,
                status: STATUS_TODO,
                title: '单词*100',
                username: '┑( ̄Д  ̄)┍',
                point: 2
            }, {
                id: 3,
                status: STATUS_TODO,
                title: '单词*150',
                username: '┑( ̄Д  ̄)┍',
                point: 2
            }, {
                id: 4,
                status: STATUS_TODO,
                title: '单词*200',
                username: '┑( ̄Д  ̄)┍',
                point: 2
            }, {
                id: 5,
                status: STATUS_TODO,
                title: '单词*250',
                username: '┑( ̄Д  ̄)┍',
                point: 2
            }]
            
            class TaskItem extends React.Component {
                handleDragStart = (e) => {
                    this.props.onDragStart(this.props.id);
                }
                render() {
                    let { id, title, point, username, active, onDragEnd } = this.props;
                    return (
                        <div 
                            onDragStart={this.handleDragStart}
                            onDragEnd={onDragEnd}
                            id={`item-${id}`} 
                            className={'item' + (active ? ' active' : '')}
                            draggable="true"
                        >
                            <header className="item-header">
                                <span className="item-header-username">{username}</span>
                                <span className="item-header-point">{point}</span>
                            </header>
                            <main className="item-main">{title}</main>
                        </div>
                    );
                }
            }
            
            class TaskCol extends React.Component {
                state = {
                    in: false
                }
                handleDragEnter = (e) => {
                    e.preventDefault();
                    if (this.props.canDragIn) {
                        this.setState({
                            in: true
                        })
                    }
                }
                handleDragLeave = (e) => {
                    e.preventDefault();
                    if (this.props.canDragIn) {
                        this.setState({
                            in: false
                        })
                    }
                }
                handleDrop = (e) => {
                    e.preventDefault();
                    this.props.dragTo(this.props.status);
                    this.setState({
                        in: false
                    })
                }
                render() {
                    let { status, children } = this.props;
                    return (
                        <div 
                            id={`col-${status}`} 
                            className={'col'}
                            onDragEnter={this.handleDragEnter}
                            onDragLeave={this.handleDragLeave}
                            onDragOver={this.handleDragEnter}
                            onDrop={this.handleDrop}
                            draggable="true"
                        >
                            <header className="col-header">
                                {STATUS_CODE[status]}
                            </header>
                            <main className={'col-main' + (this.state.in ? ' active' : '')}>
                                {children}
                            </main>
                        </div>
                    );
                }
            }
            
            class App extends React.Component {
                state = {
                    tasks: tasks,
                    activeId: null
                }
                /**
                 * 传入被拖拽任务项的 id
                 */
                onDragStart = (id) => {
                    this.setState({
                        activeId: id
                    })
                }
                
                dragTo = (status) => {
                    let { tasks,  activeId} = this.state;
                    let task = tasks[activeId];
                    if (task.status !== status) {
                        task.status = status;
                        this.setState({
                            tasks: tasks
                        })
                    }
                    this.cancelSelect();
                }
                
                cancelSelect = () => {
                    this.setState({
                        activeId: null
                    })
                }
                
                render() {
                    let { tasks, activeId } = this.state;
                    let { onDragStart, onDragEnd, cancelSelect } = this;
                    return (
                        <div className="task-wrapper">
                            {
                                Object.keys(STATUS_CODE).map(status => 
                                    <TaskCol 
                                        status={status} 
                                        key={status} 
                                        dragTo={this.dragTo}
                                        canDragIn={activeId != null && tasks[activeId].status !== status}>
                                        { tasks.filter(t => t.status === status).map(t => 
                                            <TaskItem
                                                key={t.id}
                                                active={t.id === activeId}
                                                id={t.id}
                                                title={t.title} 
                                                point={t.point} 
                                                username={t.username}
                                                onDragStart={onDragStart}
                                                onDragEnd={cancelSelect}
                                            />)
                                        }
                                    </TaskCol>
                                )
                            }
                        </div>
                    )
                }
            }
            
            ReactDOM.render(
                <App />,
                document.getElementById('app')
            );
        </script>
    </body>
</html>

四、效果

四、演示地址:

  查看演示

 

五、原文来源

  【我不吃饼干呀】 的博客 文章

posted @ 2020-11-11 11:14  艺术诗人  阅读(4857)  评论(0编辑  收藏  举报