> ## Content Index
> Fetch the complete content index at: https://iiong.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# 前端拖拽组件实践
- URL: https://iiong.com/front-end-dnd-practice-notes/
- Published: 2022-03-07T12:22:31.000Z
- Updated: 2026-06-22T15:32:04.000Z
- Description: 这几年做的可视化项目越来越多，这需要前端的 drag 和 drop 元素能力（下文简称 dnd），dnd 能力极大提高前端交互能力。然而在开发项目期间很少去了解其运行原理，这段时间趁着空余时间算是系统学习下前端 dnd 事件能力吧。
- Author: 淮城一只猫
- Tags: 编程技术, Web 前端

### 前言

这几年做的可视化项目越来越多，这需要前端的 `drag` 和 `drop` 元素能力（下文简称 `dnd`），`dnd` 能力极大提高前端交互能力。然而在开发项目期间很少去了解其运行原理，这段时间趁着空余时间算是系统学习下前端 `dnd` 事件能力吧。

上面讲述到的 `drag` 和 `drop` 是前端元素上的事件，除了监听这俩个事件之外，还需要对元素进行拖拽支持：

```html
<style>
  .drag {
    position: relative;
    width: 100px;
    height: 100px;
    color: #fff;
    text-align: center;
    line-height: 100px;
    background: #ccc;
    user-select: none;
    cursor: grab;
  }
  .drop {
    position: absolute;
    top: 0;
    left: 200px;
    width: 400px;
    height: 400px;
    background: #eee;
  }
</style>

<div class="app-wrapper">
  <div class="drag-wrapper">
    <div draggable="true" id="dragger" class="drag">
      拖动元素
    </div>
  </div>
  <div class="drop-wrapper">
    <div class="drop">
      放置区域
    </div>
  </div>
</div>

```

只需要在需要拖拽的元素上添加 `draggable` 属性，该属性的值是布尔值：

- `true` 表示元素可以被拖动
- `false` 表示元素不可以被拖动

简单的拖拽例子就这样出来了，但还是远远不够，需要监听对应的事件来满足某些需求。

### 事件

`dnd` 事件主要分为拖拽和放置俩大事件类型。

拖拽事件如下：

- `dragstart` 开始拖拽元素返回回调事件
- `drag` 拖拽期间一定频率返回回调事件
- `dragend` 拖拽结束返回回调事件

放置事件如下：

- `dragenter` 当拖拽元素拖到可放置元素时候返回回调事件
- `dragover` 当拖拽元素拖到可放置元素期间一定频率返回回调事件
- `dragleave` 当拖拽元素离开可放置元素时候返回回调事件
- `drop` 当拖拽元素在放置元素放置返回回调事件

### 拖拽数据

上面列出都会有 `DragEvent` 回调事件，回调事件中有个 `dataTransfer` 属性，关于他的介绍如下：

> DataTransfer 对象用于保存拖动并放下（drag and drop）过程中的数据。它可以保存一项或多项数据，这些数据项可以是一种或者多种数据类型。

这个属性主要包含：

- `dropEffect`
- `effectAllowed`
- `files` 包含数据传输中可用的所有本地文件的列表。
- `items`（只读）
- `types`（只读）

`dropEffect` 属性拖放操作的视觉效果：

- `none`
- `copy`
- `link`
- `move`

`effectAllowed` 用来指定当元素被拖放式所允许的视觉效果：

- `none`
- `move`
- `copy`
- `link`
- `copyMove`
- `copyLink`
- `linkMove`
- `all`

```javascript
element.addEventListener('dragenter', event => {
  event.dataTrasfer.dropEffect = 'move'
})

```

下面的例子可以利用 `dataTransfer` 属性将拖拽的元素在放置元素上起到放置效果作用：

```html
<style>
  body {
    background-color: #F1C40F;
    font-family: "Courier New";
  }

  .container {
    display: grid;
    grid-template-columns: 33% 33% 33%;
  }

  .draggable, .droptarget {
    border: 20px solid white;
    margin: 30px;
    padding: 30px;
    text-align: center;
    color: white;
    font-size: 2rem;
  }

  .one {
    background-color: #f15e0f;
  }
  .two {
    background-color: #a532f1;
  }
  .three {
    background-color: #2274a5;
  }

  .droptarget {
    border: 10px dashed white;
    transition: border-width 0.5s linear;
  }

  .hover {
    border-width: 20px;
  }

</style>
<div class="container">
  <div class="draggable one" draggable="true">
    drag me
  </div>
  <div class="draggable two" draggable="true">
    drag me
  </div>
  <div class="draggable three" draggable="true">
    drag me
  </div>
  <div class="droptarget">drop here</div>
  <div class="droptarget">drop here</div>
  <div class="droptarget">drop here</div>
</div>

```

```javascript
document.querySelectorAll('.draggable').forEach(item => {
  item.addEventListener('dragstart', event => {
    event.dataTransfer.setData('text/plain', getComputedStyle(item).backgroundColor)
  })
})

document.querySelectorAll('.droptarget').forEach(item => {
  item.addEventListener('dragover', event => {
    event.preventDefault()
  })
  item.addEventListener('dragleave', event => {
    item.classList.remove('hover')
  })
  item.addEventListener('dragenter', event => {
    item.classList.add('hover')
  })

  item.addEventListener('drop', event => {
    item.style.backgroundColor = event.dataTransfer.getData('text/plain')
  })
})

```

利用 `setData` 方法设置对拖拽元素写入特定的信息，然后在放置元素读取信息来展示不同的效果。

### 结语

静下心来过一下其实这些东西也没那么复杂，看完之后对那些 `dnd` 轮子项目也差不多了解其中的架构吧。

参考资料：

- [HTML Drag and Drop API](https://developer.mozilla.org/en-US/docs/Web/API/HTML%5FDrag%5Fand%5FDrop%5FAPI?ref=iiong.com)
- [Drop Event](https://developer.mozilla.org/en-US/docs/Web/API/Document/drag%5Fevent?ref=iiong.com)
- [Draggable](https://developer.mozilla.org/en-US/docs/Web/HTML/Global%5Fattributes/draggable?ref=iiong.com)