Vue implements multi-column layout drag

Vue implements multi-column layout drag

This article shares the specific code of Vue to implement multi-column layout drag for your reference. The specific content is as follows

1. Objectives

Vue implements free dragging and width change of multiple boxes (users decide the number of boxes based on actual scenarios).

2. Application Scenarios

Multi-column layout with freely draggable width.

The most typical case: editor (eg: vscode, idea, etc.)

Component Design

Since the number of boxes of this component is uncertain, we referred to the design of Form and FormItem in Vuetify when designing the component. That is, the outer large box handles the distributed drag events, and the inner box is responsible for displaying the contents of each Item.

Component design achieves the following goals:

<drag-box style="width: 100%; height: 100%;">
   <drag-item>item1</drag-item>
   <drag-item>item2</drag-item>
   <drag-item>item3</drag-item>
   <drag-item>item4</drag-item>
</drag-box>

4. Implementation

4.1 dragBox static page

(Nesting of sub-elements is achieved through slots)

<template>
    <div ref='dragBox' style='display: flex; width: 100%; height: 100%;'>
        <slot></slot>
    </div>
</template>

4.2 dragItem page

(Nesting of drag-item internal elements is achieved through slots)

<template>
    <div ref="container" class="d-flex" style="min-width: 200px; position: relative;">
        <div style="width: 100%; height: 100%;">
            <slot>Default information</slot>
        </div>
  <!-- Drag bar -->
        <div v-if="resizeShow" class="resize" />
    </div>
</template>
<script>
export default {
  props: {
  // Controls whether the drag bar is displayed, the default is to display resizeShow: {
      type: Boolean,
      default: true
    }
  }
}
</script>
<style>
.resize {
    position: absolute;
    top: 0;
    right: 0;
    width: 4px;
    height: 100%;
    cursor: col-resize;
    background-color: #d6d6d6;
}
</style>

4.3 Drag Logic

The drag logic should be handled by dragBox, not dragItem.

4.3.1 Before implementing dragging, child elements (i.e. dragItem) should be properly laid out.

When the user does not assign an initial width to the dragItem , the default flex:1 is used (the remaining space is evenly distributed). The specific logic is as follows:

 // If dragItem does not define width, flex=1
    setDragItemFlex () {
      const dragBox = this.$refs.dragBox
      const childrenLen = dragBox.children.length

      for (let i = 0; i < childrensLen; i++) {
        const node = dragBox.children[i]
        if (!node.style.width) {
          // If width is not defined, flex=1
          node.style.flex = 1
        }
      }
    },

4.3.2 Drag and drop implementation logic

Drag events should be added for each dragItem's drag bar. The complete drag event includes: mouse press, mouse move, and mouse lift (end of dragging).

Loop to add events for each drag bar:

dragControllerDiv () {
  const resize = document.getElementsByClassName('resize') // Drag bar // Loop to add events for each drag bar for (let i = 0; i < resize.length; i++) {
    // Mouse press event resize[i].addEventListener('mousedown', this.onMouseDown)
  }
},

Mouse press logic: Get the initial position of the mouse, change the color of the drag bar, and add listener events for move and up.

onMouseDown (e) {
  this.resizeBox = e.target
  this.currentBox = this.resizeBox.parentNode // Current box this.rightBox = this.getNextElement(this.currentBox) // Next sibling node of the current box if (!this.rightBox) return
  this.curLen = this.currentBox.clientWidth
  this.otherBoxWidth = this.$refs.dragBox.clientWidth - this.currentBox.clientWidth - this.rightBox.clientWidth // Width of other boxes // Color change reminder this.resizeBox.style.background = '#818181'
  this.startX = e.clientX
  document.addEventListener('mousemove', this.onMousemove)
  document.addEventListener('mouseup', this.onMouseup)
},

// Get the next sibling element compatible function getNextElement (element) {
  if (element.nextElementSibling) {
    return element.nextElementSibling
  } else {
    var next = element.nextSibling // Next sibling node while (next && next.nodeType !== 1) { // It exists and it's not what I want next = next.nextSibling
    }
    return next
  }
}

Mouse move event: Calculate and set the width of the current box and the right box.

onMousemove (e) {
  const endX = e.clientX
  const moveLen = endX - this.startX // (endx-startx) = moving distance const CurBoxLen = this.curLen + moveLen // resize[i].left + moving distance = final width of the left area const rightBoxLen = this.$refs.dragBox.clientWidth - CurBoxLen - this.otherBoxWidth // Right width = total width - left width - other box width // When the minimum width is reached, dragging is unavailable if (CurBoxLen <= 200 || rightBoxLen <= 200) return
  this.currentBox.style.width = CurBoxLen + 'px' // Current box width this.resizeBox.style.left = CurBoxLen // Set the width of the left area this.rightBox.style.width = rightBoxLen + 'px'
},

Mouse up event: destroy mousedown and mousemove events; restore the color of the drag bar.

onMouseup () {
 // Color restoration this.resizeBox.style.background = '#d6d6d6'
 document.removeEventListener('mousedown', this.onMouseDown)
 document.removeEventListener('mousemove', this.onMousemove)
},

Add corresponding events in the mounted hook function.

mounted () {
  this.setDragItemFlex()
  this.dragControllerDiv()
},

Import and register the component:

<template>
  <div id="app" style="width: 100%; height: 100vh; border:1px solid #ccc;">
    <drag-box style="width: 100%; height: 100%;">
      <drag-item style="width: 20%;">item1</drag-item>
      <drag-item>item2</drag-item>
      <drag-item style="width: 20%;" :resizeShow='false'>item3</drag-item>
    </drag-box>
  </div>
</template>

<script>
import {DragBox, DragItem} from './components/dragLayouter'

export default {
  name: 'App',
  components:
    DragBox,
    DragItem
  }
}
</script>

5. Operation Results

The specific style can be modified later.

The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM.

You may also be interested in:
  • Vue3.0 uses the vue-grid-layout plug-in to implement drag layout
  • Vue3 draggable left and right panel split component implementation
  • Implementation of Vue code splitting (codesplit)
  • Vue implements drag-and-drop split layout

<<:  Teach you how to build Tencent Cloud Server (graphic tutorial)

>>:  How to verify whether MySQL is installed successfully

Recommend

Tips for viewing History records and adding timestamps in Linux

Tips for viewing History records and adding times...

Getting Started Guide to Converting Vue to React

Table of contents design Component Communication ...

FlashFXP ftp client software registration cracking method

The download address of FlashFXP is: https://www....

Several ways to implement CSS height changing with width ratio

[Solution 1: padding implementation] principle: I...

Best Practices Guide for MySQL Partitioned Tables

Preface: Partitioning is a table design pattern. ...

Detailed process of installing the docker plugin in IntelliJ IDEA (2018 version)

Table of contents 1. Development Environment 2. I...

Practice of using SuperMap in Vue

Table of contents Preface Related Materials Vue p...

Query the data of the day before the current time interval in MySQL

1. Background In actual projects, we will encount...

MySQL 8.0.19 Installation Tutorial

Download the installation package from the offici...

Getting Started Tutorial on Animating SVG Path Strokes Using CSS3

Without relying on JavaScript, pure CSS is used t...

A collection of information about forms and form submission operations in HTML

Here we introduce the knowledge about form elemen...

Steps to package and deploy the Vue project to the Apache server

In the development environment, the vue project i...

What does mysql database do

MySQL is a relational database management system ...