发布于 2026-01-05 7 阅读
0

🚀 仅用 16 行 JavaScript 代码即可实现强大的拖放功能

🚀 仅用 16 行 JavaScript 代码即可实现强大的拖放功能

拖放功能在应用程序中非常实用,它可以简化用户操作流程的很大一部分。然而,我们通常会将这项任务委托给其他库,但这些库可能会使应用程序变得臃肿。其实,如果您只需要一个非常简单的实现,就可以使用拖放 Web API今天,我将向您展示如何做到这一点!

我们正在制作

这是我们计划构建的基本实现方案:

这段代码只用了 16 行 JavaScript 代码就实现了!

再添加几行代码,我们就能添加更多附加功能!这里有一个包含更多功能的演示!

多试几次,你会发现我们可以

  • 仅在特定位置放置元素
  • 为我们放入的元素设置样式
  • 为拖动元素的原始副本设置样式
  • (只需一点小技巧)甚至可以自定义拖动元素的样式!

这一切仅用了30行代码!

它几乎可以在所有桌面浏览器上运行,甚至部分支持 IE 6(!),这应该足以让它正常工作,但它在某些移动浏览器上无法运行。

您可以在这里查看最新的 CanIUse 数据:

来自 caniuse.com 的关于主流浏览器对拖放功能支持情况的数据

使用库来实现这种非常基本的功能对我来说很麻烦,为了避免你们也遇到同样的问题,我想在这里记录一下这个过程!

HTML结构

可以拖进去的地方

你需要一些放置目标才能把东西拖进去,对吧?我们可以使用普通的div元素来添加这些目标:

<div class='drop'></div>
<div class='drop'></div>
<div class='drop'></div>
<div class='drop'></div>

Enter fullscreen mode Exit fullscreen mode

注:在本文中,我将把我们可以空降的地点称为空降目标。

您可以随意添加任意数量的元素,只要元素具有drop我们能够放入其中的类即可。

我们还可以添加一些基本样式,让它们看起来更美观。

* {
    box-sizing: border-box;
    font-family: sans-serif;
}

.drop {
    width: 220px;
    height: 45px;
    background: #2563EB;
    margin-bottom: 10px;
    padding: 10px;
    border-radius: 3px;
}

Enter fullscreen mode Exit fullscreen mode

要拖动的元素

要让元素可拖动,我们首先需要一个元素!我们可以将元素放置在之前创建的放置目标之一中。它应该看起来像这样。

<div class='drop'>
    <div id='drag' draggable='true' ondragstart='event.dataTransfer.setData('text/plain', null)'>
        Drag me!
    </div>
</div>
<div class='drop'></div>
<div class='drop'></div>
<div class='drop'></div>

Enter fullscreen mode Exit fullscreen mode

注意我们还将该draggable属性设置为 true。每个可拖动元素都需要draggable设置此属性才能实现拖动。

此外,即使draggable设置了属性,也并非所有元素都可以拖动。我们需要通过监听dragstartHTML 中的事件来显式地声明元素是可拖动的。null由于我们没有任何数据要共享,因此我们在这里设置了数据类型text/plain

我们还可以(再次)添加一些基本样式,让它们看起来更美观。

#drag {
    width: 200px;
    height: 25px;
    border-radius: 3px;
    background: black;
    color: white;
    display: grid;
    align-items: center;
    justify-content: center;
}

Enter fullscreen mode Exit fullscreen mode

请注意,只要元素draggable设置了属性true并且放置目标具有drop类,以下代码应该就能在所有地方正常工作。

最小实现

为了实现拖放功能,我们只需要 3 个不同的事件监听器。其他的都是锦上添花。

首先,我们需要存储正在拖动的元素。我们可以通过监听dragstart事件来实现这一点。

let dragged;

document.addEventListener('dragstart', event => {
    dragged = event.target;
}, false)

Enter fullscreen mode Exit fullscreen mode

每当拖动一个元素时,该元素都会被存储在一个变量中。

接下来,我们可以监听放置事件,以便放置元素。

document.addEventListener('drop', event => {
    // Prevent default behaviour (sometimes opening a link)
    event.preventDefault();

    if (event.target.className === 'drop') {
        dragged.parentNode.removeChild(dragged);
        event.target.appendChild(dragged);
    }
}, false)

Enter fullscreen mode Exit fullscreen mode

无论何时我们放置一个元素,如果该元素是放置目标(具有drop类),我们将把拖动的元素附加到放置目标上。

我们快要完成了,但还需要做一件事才能使之成功。

默认情况下,拖动元素不会执行任何操作,因此为了防止默认行为,我们需要event.preventDefault在每次拖动到放置目标上时调用该函数。

用一行代码就能轻松实现:

document.addEventListener('dragover', event => event.preventDefault(), false);

Enter fullscreen mode Exit fullscreen mode

搞定!只用了16行代码,我们就实现了拖放功能!

以下是它的运行视频:

最小拖放

添加更多功能

即使这种拖放功能有效,也并不好用,感觉不够“自然”。幸运的是,只需几行代码,我们就可以让这种拖放功能变得更好!

对原始拖动元素进行样式设置

当我们拖动一个元素时,该元素的原始副本样式不会改变。如果我们能为这些被拖动的元素添加不同的样式,例如使其透明以显示正在被拖动,效果会更好。

这很容易做到。只需在事件监听器中添加样式即可dragstart

document.addEventListener('dragstart', event => {
    // ...

    event.target.style.opacity = 0.5;
    // add more styles as you like...

    // ...
});

Enter fullscreen mode Exit fullscreen mode

但是,拖拽完成后我们也需要重置样式。我们可以通过监听以下事件来实现dragend

document.addeventListener('dragend', event => event.target.style.opacity = '', false)

Enter fullscreen mode Exit fullscreen mode

设置落靶样式

我们还可以通过监听dragenter事件来设置目标位置的样式:

document.addEventListener('dragenter', event => {
    if (event.target.className === 'drop') event.target.style.background = '#2c41cc';
}, false)

Enter fullscreen mode Exit fullscreen mode

同样,离开元素后我们需要重置样式。我们可以通过监听以下事件来实现dragleave

document.addEventListener('dragleave', event => {
    if (event.target.className === 'drop') event.target.style.background = '';
}, false)

Enter fullscreen mode Exit fullscreen mode

事件停止后,我们还需要重置样式。我们可以通过编辑drop事件来实现这一点。

document.addEventListener('drop', event => {
    // ...

    if (event.target.className === 'drop') {
        event.target.style.background = '';
    //...
})

Enter fullscreen mode Exit fullscreen mode

设置拖拽文本的样式

通过一些技巧,我们也可以对拖动的文本进行样式设置!或许我们可以稍微旋转一下元素,让它看起来更自然一些。

我们可以通过设置原始文本的样式,然后在dragstart事件中立即撤销这些样式来实现这一点,这样用户就看不到它了。

listen('dragstart', event => {
    // ...

    event.target.style.transform = 'rotate(-2deg)';
    setTimeout(() => event.target.style.transform = '', 1);
})

Enter fullscreen mode Exit fullscreen mode

现在,拖动复制的图形时,它看起来会旋转!

您现在拥有一个功能齐全的拖放功能!

以下是它的运行视频:

完全拖放.gif

这里有一个包含所有源代码的 Gist,供您参考。

结论

我们把一项通常会委托给库来完成的任务,自己实现了,而且代码量出奇地少。

我希望这能让你意识到,仅仅使用原生 JavaScript 就能完成很多事情。你并非每次都需要库。

你有没有尝试过自己实现拖放功能?欢迎在评论区分享!

文章来源:https://dev.to/siddharthshyniben/a-powerful-drag-and-drop-implementation-in-just-16-lines-of-javascript-d5d