当前位置:网站首页>How to play sortable JS vuedraggable to realize nested drag function of forms

How to play sortable JS vuedraggable to realize nested drag function of forms

2020-11-06 20:37:00 Tell me Zhan to hide

In recent days, I have been studying about vue Drag and drop , But it's a little different from the general drag sort , This requirement may include multi row and multi column nested form elements , Data is also recursive . I'm also in vuedraggable Based on the extension of the implementation of , How to learn more about the drag and drop sorting function can refer to https://sortablejs.github.io/Vue.Draggable/#/simple

Functions to be implemented

  1. Form elements may be nested , Data appears in a tree structure
  2. Drag and drop , Form elements can be moved to empty Columns , But the content of form elements can't be sorted back and forth
  3. Rows can be sorted by dragging between rows , Columns and columns cannot be moved directly , All that can be moved is field data, that is, form elements
  4. The fields in the list on the right can be added to the blank column with no content on the left

The technical point to use

  1. vue Component recursive implementation
  2. vuedraggable Drag sort
  3. vuedraggable Example Functional third party, It's mainly the movement of elements
  4. vuedraggable Drag and drop copy
  5. vuetify :vue ui Components , It mainly uses its lattice system and vcard card

Part of the code that implements the function

Drag Components are also component code to be recursive

<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"
        >
          <!--  Add judgment if item There is rows Array , Then recursion continues to execute the component -->
          <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: {
   
  //  Ways to limit movement 
    getData (e, d) {
   
      if (e.relatedContext.list.length > 0) {
   
        return false
      }
    },
    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)
    },
    //  Recursively traverse the data 
    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>

Be careful : Implementation of recursion, a certain definition Drag Component's name value , Or it's easy to report a mistake

 Insert picture description here
emptyInsertThreshold: OnSwipe , The distance between the mouse and the empty sortable object ( In pixels ), To insert drag elements into the sortable object . The default is 5. Set to 0 Disable this feature . This parameter should be set properly , If it's the default value , When the column is empty , It's hard to drag elements in , This is also a more difficult point to solve , Because you need to drag the right field element to the left empty column , Or the element on the left moves to the empty column .
move Corresponding method getData The main implementation of the method is if relatedContext.list.length Greater than 0, Then cancel the mobile function .
Drag The data of :

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: []
            }
            
          ]
        }
      ]

The component code in 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 1',
          items: [
            {
   
              id: 11,
              title: 'item 11'
            },
            {
   
              id: 12,
              title: 'item 12'
            }
          ]
        },
        {
   
          id: 2,
          title: ' title 2',
          items: [
            {
   
              id: 21,
              title: 'item 21'
            },
            {
   
              id: 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>

clone Of cloneDog Method to implement the copy function , First, recursively loop the data to determine whether the element to be copied exists in the list on the left , If it exists , Then cancel the copy , non-existent , Copy .

The effect is as follows :
 Insert picture description here

summary

The main technical points shared in this article are vuedraggable Drag and drop sort and copy 、 Nested drag and drop sorting function 、vue Component recursion function .

版权声明
本文为[Tell me Zhan to hide]所创,转载请带上原文链接,感谢