vanilla_如何使用Vanilla JavaScript和HTML创建拖放元素

暴辰龙
2023-12-01

vanilla

介绍 (Introduction)

Dragging-and-dropping is a common user interaction that you can find in many graphical user interfaces.

拖放是常见的用户交互,您可以在许多图形用户界面中找到它们。

There are pre-existing JavaScript libraries for adding a drag-and-drop feature to your app. However, there may be situations where a library is not available or introduces an overhead or dependency that your project does not need. In these situations, knowledge of the APIs available to you in modern web browsers can offer alternative solutions.

有预先存在JavaScript库,可用于向您的应用添加拖放功能。 但是,在某些情况下,库不可用,或者会引入项目不需要的开销或依赖项。 在这些情况下,了解现代网络浏览器中可用的API可以提供替代解决方案。

The HTML Drag and Drop API relies on the DOM’s event model to get information on what is being dragged or dropped and to update that element on drag or drop. With JavaScript event handlers, you can turn any element into a draggable item or an item that can be dropped into.

HTML拖放API依赖于DOM的事件模型来获取有关被拖放内容的信息,并在拖放时更新该元素。 使用JavaScript事件处理程序,您可以将任何元素变成可拖动的项目或可以放入的项目。

In this tutorial, we will build a drag-and-drop example using the HTML Drag and Drop API with vanilla JavaScript to use the event handlers.

在本教程中,我们将使用HTML拖放API和原始JavaScript构建一个拖放示例,以使用事件处理程序。

先决条件 (Prerequisites)

To complete this tutorial, you will need:

要完成本教程,您将需要:

  • A modern web browser that supports the Drag and Drop API (Chrome 4+, Firefox 3.5+, Safari 3.1+, Edge 18+).

    支持拖放API(Chrome 4 +,Firefox 3.5 +,Safari 3.1 +,Edge 18+)的现代网络浏览器。

第1步-创建项目和初始标记 (Step 1 — Creating the Project and Initial Markup)

Our project will consist of a container with two types of child elements:

我们的项目将包含具有两种子元素的容器:

  • Child elements that can you can drag

    您可以拖动的子元素
  • Child elements that can have elements dropped into them

    可以将元素放入其中的子元素

First, open your terminal window and create a new project directory:

首先,打开终端窗口并创建一个新的项目目录:

  • mkdir drag-and-drop-example

    mkdir 拖放示例

Next, navigate to that directory:

接下来,导航到该目录:

  • cd drag-and-drop-example

    cd 拖放示例

Then, create an index.html file in that directory:

然后,在该目录中创建一个index.html文件:

  • nano index.html

    纳米index.html

Next, add boilerplate code for a HTML webpage:

接下来,为HTML网页添加样板代码:

index.html
index.html
<!DOCTYPE html>
<html>
  <head>
    <title>My Drag-and-Drop Example</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
  </body>
</html>

And between the <body> tags add your draggable item and your dropzone (drop target):

和之间<body>标签添加你draggable项目,您的dropzone (放置目标):

index.html
index.html
<div class="example-parent">
  <div class="example-origin">
    <div
      id="draggable-1"
      class="example-draggable"
    >
      draggable
    </div>
  </div>

  <div
    class="example-dropzone"
  >
    dropzone
  </div>
</div>

Save and close the file. Then, create a style.css file:

保存并关闭文件。 然后,创建一个style.css文件:

  • nano style.css

    纳米样式

Next, add styles for the elements in our index.html file:

接下来,在index.html文件中为元素添加样式:

style.css
style.css
.example-parent {
  border: 2px solid #DFA612;
  color: black;
  display: flex;
  font-family: sans-serif;
  font-weight: bold;
}

.example-origin {
  flex-basis: 100%;
  flex-grow: 1;
  padding: 10px;
}

.example-draggable {
  background-color: #4AAE9B;
  font-weight: normal;
  margin-bottom: 10px;
  margin-top: 10px;
  padding: 10px;
}

.example-dropzone {
  background-color: #6DB65B;
  flex-basis: 100%;
  flex-grow: 1;
  padding: 10px;
}

This will add some formatting to the app. Now you can view index.html in the browser and observe that this produces a draggable <div> and a dropzone <div>.

这将为应用程序添加一些格式。 现在,您可以在浏览器中查看index.html ,并观察到这将产生draggable <div>dropzone <div>

Next, we will explicitly make the first <div> draggable by adding the draggable attribute:

接下来,我们将通过添加draggable属性显式地使第一个<div>draggable

index.html
index.html
<div class="example-parent">
  <div class="example-origin">
    <div
      id="draggable-1"
      class="example-draggable"
      draggable="true"
    >
      draggable
    </div>
  </div>

  <div
    class="example-dropzone"
  >
    dropzone
  </div>
</div>

Save and close the file.

保存并关闭文件。

Finally, view index.html in the browser again. If we click on the draggable <div> and drag it across the screen, there should be a visual indication of it moving.

最后,再次在浏览器中查看index.html 。 如果我们单击draggable <div>并将其拖动到屏幕上,则应该有直观的迹象表明它在移动。

The default value for the draggable attribute is auto. That means whether the element is draggable will be determined by your browser’s default behavior. Typically this means text selections, images, and links are draggable without specifying draggable="true".

draggable属性的默认值为auto 。 这意味着该元素是否可拖动将取决于浏览器的默认行为。 通常,这意味着无需选择draggable="true"即可draggable="true"文本选择,图像和链接。

You now have an HTML file with a draggable element. We will move on to adding onevent handlers.

现在,您有了一个带有可拖动元素HTML文件。 我们将继续添加onevent处理程序。

第2步-使用JavaScript处理拖放事件 (Step 2 — Handling Drag-and-Drop Events with JavaScript)

Currently, if we release the mouse while dragging the draggable element, nothing happens. To trigger an action on drag or drop on DOM elements, we’ll need to utilize the Drag and Drop API:

当前,如果我们在拖动可拖动元素的同时释放鼠标,则什么也不会发生。 要触发对DOM元素的拖放操作,我们需要利用拖放API:

  • ondragstart: This event handler will be attached to our draggable element and fire when a dragstart event occurs.

    ondragstart :此事件处理程序将附加到我们的draggable元素,并在发生dragstart事件时触发。

  • ondragover: This event handler will be attached to our dropzone element and fire when a dragover event occurs.

    ondragover :此事件处理程序将附加到我们的dropzone元素,并在发生dragover事件时触发。

  • ondrop: This event handler will also be attached to our dropzone element and fire when a drop event occurs.

    ondrop :此事件处理程序也将附加到我们的dropzone元素,并在发生drop事件时触发。

Note: There are eight event handlers in total: ondrag, ondragend, ondragenter, ondragexit, ondragleave, ondragover, ondragstart, and ondrop. For our example, we will not require them all.

注意:总共有八个事件处理程序: ondragondragendondragenterondragexitondragleaveondragoverondragstartondrop 。 对于我们的示例,我们将不需要全部。

First, let’s reference a new script.js file in our index.html:

首先,让我们在index.html引用一个新的script.js文件:

index.html
index.html
<body>
  ...
  <script src="script.js"></script>
</body>

Next, create a new script.js file:

接下来,创建一个新的script.js文件:

  • nano script.js

    纳米script.js

The DataTransfer object will keep track of the information related to the current drag happening. To update our element on drag and on drop, we need to directly access the DataTransfer object. To do this, we can select the dataTransfer property from the DOM element’s DragEvent.

DataTransfer对象将跟踪与当前拖动发生有关的信息。 要在拖放时更新元素,我们需要直接访问DataTransfer对象。 为此,我们可以从DOM元素的DragEvent选择dataTransfer属性。

Note: The DataTransfer object can technically track information for multiple elements being dragged at the same time. For our example, we’ll focus on dragging one element.

注意: DataTransfer对象可以从技术上跟踪同时拖动的多个元素的信息。 对于我们的示例,我们将集中于拖动一个元素。

The dataTransfer object’s setData method can be used to set the drag state information for your currently dragged element. It takes two parameters:

dataTransfer对象的setData方法可用于设置当前拖动元素的拖动状态信息。 它带有两个参数:

  • a string that declares the format of the second parameter

    声明第二个参数格式的字符串
  • the actual data being transferred

    实际传输的数据

Our goal is to move our draggable element to a new parent element. We need to be able to select our draggable element with a unique id. We can set the id of the dragged element with the setData method so it can be used later.

我们的目标是将draggable元素移动到新的父元素。 我们需要能够选择具有唯一id draggable元素。 我们可以使用setData方法设置拖动元素的id ,以便以后使用。

Let’s revisit our script.js file and create a new function to use setData:

让我们重新访问script.js文件并创建一个新函数以使用setData

script.js
script.js
function onDragStart(event) {
  event
    .dataTransfer
    .setData('text/plain', event.target.id);
}

Note: Internet Explorer 9 through 11 reportedly has problems with using 'text/plain'. The format needs to 'text' for that browser.

注意:据报道,Internet Explorer 9至11在使用'text/plain'存在问题。 该浏览器的格式需要为'text'

To update the dragged item’s CSS styling, we can access its styles using the DOM event again and by setting whatever styles we want for the currentTarget.

要更新所拖动项目CSS样式,我们可以再次使用DOM事件并通过为currentTarget设置所需的样式来再次访问其样式。

Let’s add to our function and change the backgroundColor to yellow:

让我们添加到函数中,并将backgroundColor更改为yellow

script.js
script.js
function onDragStart(event) {
  event
    .dataTransfer
    .setData('text/plain', event.target.id);

  event
    .currentTarget
    .style
    .backgroundColor = 'yellow';
}

Note: Any styles you change will need to be manually updated again on drop if you want drag-only styles. If you change anything when it starts dragging, the dragged element will keep that new styling unless you change it back.

注意:如果您想要仅拖动样式,则您更改的任何样式将需要在拖放时再次手动更新。 如果在开始拖动时更改了任何内容,则拖动的元素将保留该新样式,除非您将其更改回原样。

Now, we have our JavaScript function for when dragging starts.

现在,我们有了JavaScript函数,可以开始拖动。

We can add ondragstart to the draggable element in index.html:

我们可以将ondragstart添加到index.htmldraggable元素中:

index.html
index.html
<div class="example-parent">
  <div class="example-origin">
    <div
      id="draggable-1"
      class="example-draggable"
      draggable="true"
      ondragstart="onDragStart(event);"
    >
      draggable
    </div>
  </div>

  <div class="example-dropzone">
    dropzone
  </div>
</div>

View index.html in your browser. If you try to drag your item now, the styling declared in our function will get applied:

在浏览器中查看index.html 。 如果您现在尝试拖动项目,则将应用我们函数中声明的样式:

However, nothing will happen when you release your click.

但是,释放点击不会发生任何事情。

The next event handler fired in this sequence is ondragover.

按此顺序触发的下一个事件处理程序是ondragover

The default drop behavior for certain DOM elements like <div>s in browsers typically does not accept dropping. This behavior will intercept the behavior we are attempting to implement. To ensure that we get the desired drop behavior, we will apply preventDefault.

浏览器中某些DOM元素(例如<div>的默认删除行为通常不接受删除。 此行为将拦截我们尝试实现的行为。 为了确保获得所需的放置行为,我们将应用preventDefault

Let’s revisit the script.js file and create a new function to use preventDefault. Add this code to the end of the file:

让我们重新访问script.js文件并创建一个新函数以使用preventDefault 。 将此代码添加到文件末尾:

script.js
script.js
function onDragOver(event) {
  event.preventDefault();
}

Now, we can add ondragover to our dropzone element in index.html:

现在,我们可以在index.html中将ondragover添加到我们的dropzone元素中:

index.html
index.html
<div class="example-parent">
  <div class="example-origin">
    <div
      id="draggable-1"
      class="example-draggable"
      draggable="true"
      ondragstart="onDragStart(event);"
    >
      draggable
    </div>
  </div>

  <div
    class="example-dropzone"
    ondragover="onDragOver(event);"
  >
    dropzone
  </div>
</div>

At this point, we still have not written code handle the actual dropping. The final event handler fired in this sequence is ondrop.

在这一点上,我们还没有编写处理实际丢弃的代码。 按此顺序触发的最终事件处理程序为ondrop

Let’s revisit our script.js file and create a new function.

让我们重新访问script.js文件并创建一个新函数。

We can reference the data we saved earlier with dataTransfer object’s setData method. We will use dataTransfer object’s getData method. The data we set was the id, so that’s what will be returned to us:

我们可以使用dataTransfer对象的setData方法引用之前保存的数据。 我们将使用dataTransfer对象的getData方法。 我们设置的数据是id ,因此将返回给我们:

script.js
script.js
function onDrop(event) {
  const id = event
    .dataTransfer
    .getData('text');
}

Select our draggable element with the id we retrieved:

选择具有我们检索到的id draggable元素:

script.js
script.js
function onDrop(event) {
  // ...

  const draggableElement = document.getElementById(id);
}

Select our dropzone element:

选择我们的dropzone元素:

script.js
script.js
function onDrop(event) {
  // ...

  const dropzone = event.target;
}

Append our draggable element to the dropzone:

将我们的draggable元素添加到dropzone

script.js
script.js
function onDrop(event) {
  // ...

  dropzone.appendChild(draggableElement);
}

Reset our dataTransfer object:

重置我们的dataTransfer对象:

script.js
script.js
function onDrop(event) {
  // ...

  event
    .dataTransfer
    .clearData();
}

Now, we can add ondrop to our dropzone element in index.html:

现在,我们可以在index.htmldropzone元素中添加ondrop

index.html
index.html
<div class="example-parent">
  <div class="example-origin">
    <div
      id="draggable-1"
      class="example-draggable"
      draggable="true"
      ondragstart="onDragStart(event);"
    >
      draggable
    </div>
  </div>

  <div
    class="example-dropzone"
    ondragover="onDragOver(event);"
    ondrop="onDrop(event);"
  >
    dropzone
  </div>
</div>

Once that’s done, we have a completed drag-and-drop feature. View index.html in your browser and drag the draggable element to the dropzone.

完成后,我们将具有完整的拖放功能。 在浏览器中查看index.html并将draggable元素拖到dropzone

Our example handles the scenario of a single draggable item and a single drop target. You can have multiple draggable items, multiple drop targets, and customize it with all the other Drag and Drop API event handlers.

我们的示例处理单个可拖动项目和单个放置目标的场景。 您可以具有多个可拖动项目,多个放置目标,并使用所有其他拖放API事件处理程序对其进行自定义。

步骤3 —构建具有多个可拖动项目的高级示例 (Step 3 — Building an Advanced Example with Multiple Draggable Items)

Here’s one more example of how you could use this API: a to-do list with draggable tasks that you can move from a "To-do" column to a "Done" column.

这是如何使用此API的另一个示例:具有可拖动任务的待办事项列表,您可以将这些任务从"To-do"列移至"Done"列。

To create your own to-do list, add more draggable elements with unique ids to index.html:

要创建自己的待办事项列表,请将更多具有唯一id的可拖动元素添加到index.html

index.html
index.html
<div class="example-parent">
  <h1>To-do list</h1>
  <div class="example-origin">
    To-do
    <div
      id="draggable-1"
      class="example-draggable"
      draggable="true"
      ondragstart="onDragStart(event);"
    >
      thing 1
    </div>
    <div
      id="draggable-2"
      class="example-draggable"
      draggable="true"
      ondragstart="onDragStart(event);"
    >
      thing 2
    </div>
    <div
      id="draggable-3"
      class="example-draggable"
      draggable="true"
      ondragstart="onDragStart(event);"
    >
      thing 3
    </div>
    <div
      id="draggable-4"
      class="example-draggable"
      draggable="true"
      ondragstart="onDragStart(event);"
    >
      thing 4
    </div>
  </div>

  <div
    class="example-dropzone"
    ondragover="onDragOver(event);"
    ondrop="onDrop(event);"
  >
    Done
  </div>
</div>

View index.html in your browser and drag the items in the To-do column to the Done column. You have created a to-do application and tested the functionality.

在浏览器中查看index.html并将“ 待办事项”列中的项目拖到“ 完成”列中。 您已创建待办事项应用程序并测试了功能。

结论 (Conclusion)

In this article, you created a to-do app to explore the drag-and-drop functionality that is available to modern web browsers.

在本文中,您创建了一个待办事项应用程序,以探索可用于现代Web浏览器的拖放功能。

The Drag and Drop API provides multiple options for customizing your actions beyond dragging and dropping. For example, you can update the CSS styling of your dragged items. Also, instead of moving the item, you can choose to copy your draggable item so that it gets replicated on drop.

拖放API除了提供拖放功能外,还提供了多个用于自定义操作的选项。 例如,您可以更新所拖动项目CSS样式。 另外,您可以选择复制可拖动的项目,以使其在拖放时被复制,而不是移动该项目。

Bear in mind that while many web browsers support this technology, you may not be able to rely on it if your audience consists of devices that do not support this functionality.

请记住,尽管许多Web浏览器都支持该技术,但是如果您的听众是由不支持此功能设备组成的,则可能无法依靠该技术。

To learn more about all you can drop with the Drag and Drop API, check out MDN’s docs on it.

要了解有关使用拖放API可以删除的所有内容的更多信息,请查看MDN的文档

翻译自: https://www.digitalocean.com/community/tutorials/js-drag-and-drop-vanilla-js

vanilla

 类似资料: