In recent days, we have been working on vUE to implement drag-and-drop functions. However, unlike normal drag-and-drop sorting, this requirement may have multiple rows and columns nested form elements, and the data is also in recursive form. I am also on the basis of vuedraggable extension, how to want to know more drag sorting can reference sortablejs. Making. IO/Vue Draggab…
Functions that need to be implemented
- Form elements may be nested, and data may appear in a tree structure
- To implement drag-and-drop, form elements can be moved to empty columns, but the contents of form elements cannot be dragged back and forth
- Row to row can be dragged to sort, column to column can not move sort, only can move field data, namely form elements
- Fields from the list on the right can be dragged and added to the blank column on the left
Use the technology point
- Vue component recursive implementation
- Vuedraggable drag sort
- The vuedraggable example, Functional Third Party, focuses on element movement
- Vuedraggable implements the drag-and-copy function
- Vuetify: Vue UI component, which mainly uses its decertify system and vcard
Part of the code to achieve the function
The Drag component is also the component code to recurse
<template> <draggable v-model="datas" tag="v-layout" class="row wrap fill-height align-center sortable-list" style="background: grey;" > <v-flex v-for="row in datas" :key="row.index" class="sorttable" xs12 my-2 style="background: red" > <div class="row wrap justify-space-around"> <v-flex v-for="item in row.items" :key="item.id" xs4 pa-3 class="row-v" > <! <template v-if="item.rows && array.isarray (item.rows)"> <drag :data="item.rows" /> </template> <draggable v-else :list="item.data" tag="div" :group="{ name: 'row'}" :move="getData" :animation="100" :empty-insert-threshold="60" @change="log" > <v-card v-for="item2 in item.data" :key="item2.title" style="height: 100px;" > {{ item2.title }} </v-card> </draggable> </v-flex> </div> </v-flex> </draggable> </template> <script> import draggable from 'vuedraggable' import Vue from 'vue' import Vuetify from 'vuetify' import 'vuetify/dist/vuetify.min.css' Vue.use(Vuetify) export default { name: 'Drag', order: 17, components: { draggable }, props: { data: { type: Array, default () { return [] } } }, data () { return { datas: this.data, controlOnStart: true } }, methods: {/ / restrictions on the movement method getData (e, d) {if (" e.r elatedContext. List the length > 0) {return false}}, the log: function (evt) { // window.console.log(evt) // console.log(this.data) if (Object.keys(evt)[0] === 'added') { this.arrLoop(this.data, evt.added.element) } }, addHandler (e, d) { // console.log(e) }, endHandler (e, B) {console.log(b)}, arrLoop (arr, ele) { arr.forEach(item => { const itemArr = item.data if (itemArr && itemArr.length > 1) { for (let i = 0; i < itemArr.length; i++) { if (itemArr[i].title === ele.title) { itemArr.splice(i, 1) } } } if (item.items && item.items.length) { this.arrLoop(item.items, ele) } }) } } } </script> <style> .buttons { margin-top: 35px; } .row-v { /* height: 150px; width: 200px; */ width: 33%; height: 100px; display: inline-block; background: blue; border: 1px solid #ebebeb; } .row { margin-left: 0; margin-right: 0; }.ghost {opacity: 0.5; background: #c8ebfb; } </style>Copy the code
Note: Implementing recursion must define the name value of the Drag component, otherwise it is likely to report an error
rows: [
{
index: 1.items: [{id: 1.data: [{
title: 'item 1'}]}, {id: 11.data: [{
title: 'item 11'}]}, {id: 12.data: []}]}, {index: 2.items: [{id: 0.rows: [{index: 1.items: [{id: 2.data: [{
title: 'item 211'}]}, {id: 3.data: [{
title: 'item 212'}}]}, {index: 2.items: [{id: 4.data: [{title: 'item 222'}]}]}, {id: 5.data: [{
title: 'item 3'}}]}, {index: 3.items: [{id: 6.data: [{
title: 'item 4'}]}, {id: 7.data: [{
title: 'item 5'}]}, {id: 8.data: []}]}]Copy the code
Component code for the list on the right:
<template> <div> <div v-for="item in datas" :key="item.id" class="item-box" > <h2>{{ item.title }}</h2> <div class="item-con"> <draggable class="dragArea list-group" :list="item.items" :group="{ name: 'row', pull: 'clone', put: false }" :clone="cloneDog" > <span v-for="item2 in item.items" :key="item2.id" > {{ item2.title }} </span> </draggable> </div> </div> </div> </template> <script> import draggable from 'vuedraggable' export default { name: 'Drag', components: { draggable }, props: { data: { type: Array, default () {return []}}}, data () {return {datas: [{id: 1, title: 'title ', items: [{id: 11, title: 'item 11'}, {id: 12, title: 'item 12'}]}, {id: 2, title: 'item 2', items: [{id: 21, title: 'item 21'}, {id: 2, title: 'item 21'}, 22, title: 'item 22' } ] } ] } }, methods: { cloneDog (ele) { // console.log(ele) let b = this.arrLoop(this.rows, ele) if (! b) { return ele } }, arrLoop (arr, ele) { for (let i = 0; i < arr.length; i++) { if (arr[i].id === ele.id) { return true } if (arr[i].items && arr[i].items.length) { return this.arrLoop(arr[i].items, ele) } } } } } </script> <style lang="scss" scoped> .list-group{ span { display: inline-block; padding: 0 12px; border-radius: 4px; border: 1px solid #ebebeb; line-height: 32px; height: 32px; background: #f5f5f5; margin-right: 15px; } } </style>Copy the code
Clone’s cloneDog method realizes the replication function. First, recursively loop the data to determine whether the element to be copied exists in the list on the left. If it does, the replication will be cancelled; if it does not, the replication will be performed.
The effect is shown below:
conclusion
The main technical points shared in this article are VueDragGable drag sort and copy, nested drag sort, and vUE component recursion. These are my personal opinions only.