How to build a drag and drop plugin using vue custom directives

How to build a drag and drop plugin using vue custom directives

We all know the drag-and-drop feature of HTML5, which can be used to easily implement drag and drop functions. For example, in some selection operation scenarios, it is easier for users to accept and understand dragging than clicking with the mouse. Today we will use this feature and combine it with vue's custom instructions to implement a simple but practical drag and drop plug-in.

Why is it called a plugin? Because our goal is not to develop a Vue component, but two Vue custom instructions, and eventually these two custom instructions will be encapsulated into an ES6 class, which can be easily used when introduced in actual projects.

Most drag-and-drop scenarios involve dragging and dropping some selected elements from area A to area B. There are two concepts involved here, one is draggable and the other is placeable. The selected element must be draggable, and the target area (container) must be placeable.

If we develop a draggable vue component, or develop a droppable component, then only this component can be dragged and dropped. At this time, if the requirements change and another component is required to support drag and drop, we still need to write drag and drop code for the other component. Or maybe other projects also need drag-and-drop functionality, and we have to redevelop it. This is not conducive to maintenance and reuse, and Vue's custom instructions help us solve this problem very well. We only need to add custom instructions to the component (including ordinary DOM elements) to make this component (element) draggable and dropable, so that we can use it flexibly.

In addition to the default built-in directives for core functionality (v-model and v-show), Vue also allows you to register custom directives. Note that in Vue 2.0, the main form of code reuse and abstraction is components. However, in some cases, you still need to perform low-level operations on ordinary DOM elements, and this is when custom instructions are used.

In summary, the goal of this article is to complete two custom instructions:

  • v-drag makes the component draggable
  • v-drop makes the component droppable

The goal is clear, so let’s get started! Since we want these two instructions to work on any component, we need to register the Vue global directive.

Vue.directive('drag', {
   bind(el, binding, vnode){
        //Called only once, when the directive is first bound to an element.
        //Here you can do a one-time initialization setup.
    }
})
Vue.directive('drop', {
   bind(el, binding, vnode){
        //
    }
})

If your project is built with vue-cli, you can write this code above the vue initialization in main.js.

We first write the code in the bind hook of the drag directive. Bind is only called once, and it is called when the directive is first bound to an element, so we use the bind hook. The goal of this directive is to make the component (element) draggable, so we set el's draggable to true

el.draggable = true;
el.ondragstart = (event)=>{
  event.dataTransfer.setData("Text", "your data...");
}

When an element is dragged, the ondragstart event is triggered first. Usually we set the drag data for the event's dataTransfer in this event. The purpose is that when the element is dropped, the target container can obtain the dragged data. If the drag and drop cannot transfer data, it will be meaningless. The above code calls the setData method of dataTransfer to set the drag data. Parameter 1 of setData indicates the data type, and parameter 2 indicates the data to be transferred.

Unfortunately, drag data currently only supports strings. If you want to pass complex objects, you can serialize the data

Next, we write code for the bind hook of the drop directive. The purpose of this directive is to make the component (element) droppable, so we need to write handlers for the element's ondragover (drag over event) and ondrop (drop event). These two handlers should prevent the default behavior of the event.

el.ondragover = (event)=>{
  event.preventDefault(); //Prevent default behavior}
el.ondrop = (event)=>{
  event.preventDefault();
  let dragData = event.dataTransfer.getData('Text'); //Get drag data}

We can get the drag data set in the drag start event through the getData method of event.dataTransfer.

Now you can add these two instructions to any component. Components with v-drag can be dragged, and components with v-drop can be placed and receive drag data.

<MyComponent v-drag></MyComponent>

<MyContainer v-drop></MyContainer>

A new problem arises. We perform the drag operation to transfer data. However, the initial stage of data transfer is performed in the bind hook of the custom instruction drag, and the receiving stage of data transfer is performed in the bind hook of drop. So, where does the data come from? Where are you going? Obviously, data should come from a component and should also be passed to another component, otherwise there is no point in us writing directives on vue components.

Fortunately, the hook function of the custom instruction provides us with the simplest and most effective way to access the component: that is the third parameter vnode of the hook function. vnode has an attribute called componentInstance. This componentInstance is the host of the custom instruction: the vue component instance!

The next step is easy. We only need to define an interface for obtaining drag data for the component with v-drag added, and define an interface for receiving drag data for the component with v-drop added. Although the Vue component does not support the definition of the interface, we can agree on the two method names and implement them in the component's method.

//Custom component internal methods:{
  getDragData(){ //getDragData is agreed to be the interface method for obtaining component drag data return this.id; //Assume that when this component is dragged, the id needs to be passed out}
  setDragData(data){ //setDragData is agreed to be the interface method for components to receive drag data this.appendNewChildById(data); //Assume that this component receives id to generate new elements}
}

Then rewrite our custom instruction to set and pass the drag data code:

let dragValue = "";
if(vnode.componentInstance.getDragData != undefined){
  dragValue = vnode.componentInstance.getDragData();
}
event.dataTransfer.setData("Text", dragValue);

ondrop event in v-drop directive

let dragValue = event.dataTransfer.getData('Text');
if(vnode.componentInstance.setDragData != undefined){
  vnode.componentInstance.setDragData(dragValue);
}

We added an if check when accessing the component's interface method, because without the interface constraint, the component may not implement these methods.

Well, here we have fully implemented the custom instructions for dragging and dropping components. Although it is simple, it is very practical and flexible, and can basically meet the needs of daily dragging and dropping. Let's summarize the whole process!

  • Customize global directives v-drag and v-drop
  • The dragged component needs to implement the interface method for obtaining data
  • The component that needs to be placed implements the interface method for receiving data
  • The drag command accesses the component's interface method to obtain data
  • The drop instruction accesses the component's interface method to pass data

We encapsulate the relevant code of the global custom directive into an es6 class and put it into the project as a separate js file, or publish it to npm, then import this class in main.js and call the static initialization method to complete the registration of the global directive. In this way, any component in the project can use v-drag and v-drop. Of the five steps summarized above, you only need to implement the second and third steps.

The above is the details of how to use vue custom instructions to build a drag and drop plug-in. For more information about vue custom instructions to build a drag and drop plug-in, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • Example code of vue using Moment plugin to format time
  • The whole process of developing a Google plug-in with vue+element
  • Example of using swiper plugin to implement carousel in Vue
  • How to introduce Excel table plug-in into Vue
  • Vue code highlighting plug-in comprehensive comparison and evaluation
  • Based on vue-simple-uploader, encapsulate the global upload plug-in function of file segment upload, instant upload and breakpoint resume
  • How to use vue-bootstrap-datetimepicker date plugin in vue-cli 3
  • Vue plugin error: Vue.js is detected on this page. Problem solved

<<:  MySQL uses find_in_set() function to implement where in() order sorting

>>:  Example of how to deploy Spring Boot using Docker

Recommend

Faint: "Use web2.0 to create standard-compliant pages"

Today someone talked to me about a website develo...

How to avoid duplication of data when inserting in MySql batch

Table of contents Preface 1. insert ignore into 2...

Detailed explanation of ECharts mouse event processing method

An event is an action performed by the user or th...

Detailed explanation of how to adjust Linux command history

The bash history command in Linux system helps to...

How to install mysql via yum on centos7

1. Check whether MySQL is installed yum list inst...

vue+springboot realizes login function

This article example shares the specific code of ...

Several mistakes that JavaScript beginners often make

Table of contents Preface Confusing undefined and...

uniapp dynamic modification of element node style detailed explanation

Table of contents 1. Modify by binding the style ...

Mysql keeps the existing content and adds content later

This command modifies the data table ff_vod and a...

JavaScript to achieve simple tab bar switching case

This article shares the specific code for JavaScr...

JavaScript single thread and asynchronous details

Table of contents 1. Task Queue 2. To explain som...

Detailed explanation of Vue's sync modifier

Table of contents 1. Instructions 2. Modifiers 3....

A brief analysis of how to upgrade PHP 5.4 to 5.6 in CentOS 7

1. Check the PHP version after entering the termi...

How to view the network routing table in Ubuntu

What are Routing and Routing Table in Linux? The ...