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

Detailed introduction to Mysql date query

Query the current date SELECT CURRENT_DATE(); SEL...

Elementui exports data to xlsx and excel tables

Recently, I learned about the Vue project and cam...

HTTP and HTTP Collaboration Web Server Access Flow Diagram

A web server can build multiple web sites with in...

How to quickly paginate MySQL data volumes of tens of millions

Preface In backend development, in order to preve...

XHTML Web Page Tutorial

<br />This article is mainly to let beginner...

js basic syntax and maven project configuration tutorial case

Table of contents 1. js statement Second, js arra...

How to reference external CSS files and iconfont in WeChat applet wxss

cause The way to import external files into a min...

Detailed explanation of Vue's live broadcast function

Recently, the company happened to be doing live b...

JavaScript to achieve product query function

This article example shares the specific code of ...

How to implement Ajax concurrent request control based on JS

Table of contents Preface Ajax serial and paralle...

How to implement Docker container self-start

Container auto-start Docker provides a restart po...

Example of implementing element table row and column dragging

The element ui table does not have a built-in dra...

Web page layout should consider IE6 compatibility issues

The figure below shows the browser viewing rate i...