首页 > 技术文章 > 使用react 实现拖拽功能

art-poet 2020-11-11 11:14 原文

一、关于拖动

图片默认可以拖动,其他元素的拖动效果同图片。正常的 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: '橘子

推荐阅读