In my spare time, I studied vueDraggable to implement drag and drop between lists. VueDraggable is a VUE plug-in packaged based on sortable.js, so you can refer to the document of Sortable. The API in Chinese document is quite complete. You can have a look if you don’t understand. The document address: www.itxst.com/sortablejs/…

Officially start ~~~~~~~ the first step, introduction, very simple and direct

npm install vuedraggable --save
Copy the code

It is then introduced in the file to be used

import draggable from 'vuedraggable'
Copy the code

Global import is in main.js

import draggable from 'vuedraggable'
Vue.use(vuedraggable)
Copy the code

The second step is to use it in template

<draggable
      id='list'
      :group='group1'
      :list="list"
      v-bind="$attrs"
      class="board-column-content"
      :move='move'
      :set-data="setData"
      @add='add'
      @start='isDragging=true'
      @end='isDragging=false'
      @choose='listChoose'
      @clone='listClone'
    >
      <div v-for="(element,index) in list" :key="index" class="board-item">
        {{ element.name }}
      </div>
    </draggable>
Copy the code

. It is the first time to write an article, there are still many shortcomings, please give me more advice. The complete code is below.

  <div class="board-column">
    <div class="board-column-header">
      {{ headerText }}
          <!-- <div> -->
      <el-button type='danger' @click='reset'>清空</el-button>
      <el-button type='primary' @click='cancel'>撤销上一步</el-button>
    <!-- </div> -->
    </div>
    <draggable
      id='list'
      :group='group1'
      :list="list"
      v-bind="$attrs"
      class="board-column-content"
      :move='move'
      :set-data="setData"
      @add='add'
      @start='isDragging=true'
      @end='isDragging=false'
      @choose='listChoose'
      @clone='listClone'
    >
      <div v-for="(element,index) in list" :key="index" class="board-item">
        {{ element.name }}
      </div>
    </draggable>
    <el-form label-width='100px' class="board-column-content-right">
    <draggable
      id='data'
      :group='group2'
      :list="listData"

      v-bind="$attrs"
      class="draggable-right"
      :set-data="setData"
      @add='add'
      @start='isDragging=true'
      @end='isDragging=false'
      @clone='dataClone'
    >
      <div v-for="(item,index) in listData" :key="index" class="content-item">
        <template v-if='item.id=="input"'>
          <el-form-item :label='item.name'>
            <el-input class='input' />
          </el-form-item>
        </template>
        <template v-else-if='item.id=="textarea"'>
          <el-form-item :label='item.name'>
            <el-input type='textarea' class='input' maxlength='500'  show-word-limit />
          </el-form-item>
        </template>
        <template v-else-if='item.id=="radio"'>
          <el-form-item :label='item.name'>
            <el-radio  v-model="radio" label="禁用">选项一</el-radio>
            <el-radio  v-model="radio" label="选中且禁用">选项二</el-radio>
          </el-form-item>
        </template>
        <template v-else-if='item.id=="checkbox"'>
          <el-form-item :label='item.name'>
            <el-checkbox-group v-model="checkValue" >
              <el-checkbox v-for="city in cities" :label="city" :key="city">{{city}}</el-checkbox>
            </el-checkbox-group>
          </el-form-item>
        </template>
        <template v-else-if='item.id=="select"'>
          <el-form-item :label='item.name'>
            <el-select v-model="selectValue" placeholder="请选择">
              <el-option
                v-for="item in selectOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value">
              </el-option>
            </el-select>
          </el-form-item>
        </template>
        <template v-else-if='item.id=="cascader"'>
          <el-form-item :label='item.name'>
            <el-cascader
              v-model="cascaderValue"
              :options="cascaderOptions">
            </el-cascader>
          </el-form-item>
        </template>
        <template v-else-if='item.id=="date"'>
          <el-form-item :label='item.name'>
            <el-date-picker
              v-model="dateValue"
              type="date"
              placeholder="选择日期">
            </el-date-picker>
          </el-form-item>
        </template>
        <!-- <template>
          {{item.name}}
        </template> -->
      </div>
    </draggable>
    </el-form>

  </div>
</template>

<script>
import draggable from 'vuedraggable'

export default {
  name: 'DragKanbanDemo',
  components: {
    draggable
  },
  data(){
    return{
      headerText:'拖拽组件',
      oldList:[],
      isDragging:false,
      list:[
        {name:'输入框',id:'input'},
        {name:'单选',id:'radio'},
        {name:'多选',id:'checkbox'},
        {name:'下拉框',id:'select'},
        {name:'级联选择',id:'cascader'},
        {name:'日期',id:'date'},
        {name:'输入区',id:'textarea'},
      ],
      listData:[
      ],
      radio:'',
      selectValue:'',
      selectOptions:[
        {label:'选项一',value:'1'},
        {label:'选项二',value:'2'},
        {label:'选项三',value:'3'}
      ],
      cascaderValue:[],
      cascaderOptions:[
        {label:'选项1',value:'1',children:[
          {label:'选项1-1',value:'1-1',children:[
            {label:'选项1-1-1',value:"1-1-1"},
            {label:'选项1-1-2',value:"1-1-2"},
            {label:'选项1-1-2',value:"1-1-2"}
          ]},
          {label:'选项1-2',value:'1-2',children:[
            {label:'选项1-2-1',value:"1-2-1"},
            {label:'选项1-2-2',value:"1-2-2"},
            {label:'选项1-2-2',value:"1-2-2"}
          ]},
          {label:'选项1-3',value:'1-3',children:[
            {label:'选项1-3-1',value:"1-3-1"},
            {label:'选项1-3-2',value:"1-3-2"},
            {label:'选项1-3-2',value:"1-3-2"}
          ]},
        ]},
        {label:'选项2',value:'2',children:[
          {label:'选项2-1',value:'2-1',children:[
            {label:'选项2-1-1',value:"2-1-1"},
            {label:'选项2-1-2',value:"2-1-2"},
            {label:'选项2-1-2',value:"2-1-2"}
          ]}
        ]},
        {label:'选项3',value:'2',children:[
          {label:'选项3-1',value:'3-1',children:[
            {label:'选项3-1-1',value:"3-1-1"},
            {label:'选项3-1-2',value:"3-1-2"},
            {label:'选项3-1-2',value:"3-1-2"}
          ]}
        ]},
        
      ],
      dateValue:'',
      checkValue:[],
      cities:['上海', '北京', '广州', '深圳'],
      group1:{ name: 'ccc', pull: 'clone' ,put: false},
      group2:{ name: 'ccc'},
    }
  },
  watch:{
    listData(n,o){
      console.log("n,o",n,o)
    }
  },
  methods: {
    move(e){
      console.log("e>>>>>",e)
    },
    dataStart(e){
      this.oldList = this.list.concat()
      this.isDragging=true;
    },  
    add(){
      console.log("...",...arguments)
    },
    dataEnd(){
      this.isDragging=false;
      this.list = this.oldList.concat()
    },
    setData(dataTransfer) { 
      // console.log("setData",dataTransfer)
      // to avoid Firefox bug
      // Detail see : https://github.com/RubaXa/Sortable/issues/1012
      dataTransfer.setData('Text', '')
    },
    listChoose(dataTransfer){
      // dataTransfer.newIndex=new Date().getTime()
      // console.log('listChoose', dataTransfer.newIndex ,dataTransfer)
    },
    listClone(dataTransfer){
      // dataTransfer.newIndex=new Date().getTime()
      console.log("listClone",dataTransfer)
    },
    dataChoose(dataTransfer){
      // console.log("dataChoose",dataTransfer)
    },
    dataClone(dataTransfer){
      // console.log("dataClone",dataTransfer)
    },
    reset(){
      this.listData = []
    },
    cancel(){
      this.listData.pop();
    }
  }
}
</script>
<style lang="scss" scoped>
.board-column {
  min-width: 300px;
  min-height: 100px;
  height: auto;
  overflow: hidden;
  background: #f0f0f0;
  border-radius: 3px;

  .board-column-header {
    height: 50px;
    line-height: 50px;
    overflow: hidden;
    padding: 0 20px;
    text-align: center;
    background: #333;
    color: #fff;
    border-radius: 3px 3px 0 0;
  }
  .board-column-content {
    // height: auto;
    overflow: hidden;
    border: 10px solid skyblue;
    box-sizing:border-box;
    display: inline-block;
    width: 11%;
    vertical-align:text-top;

    .board-item {
      text-align:center;
      cursor: pointer;
      display:inline-block;
      width: 100px;
      margin: 5px;
      background-color: #fff;
      // text-align: left;
      // line-height: 54px;
      padding: 5px 10px;
      box-sizing: border-box;
      box-shadow: 0px 1px 3px 0 rgba(0, 0, 0, 0.2);
    }
  }
.board-column-content-right{
  width:80% ;
  min-height:800px;
  // border:10px solid purple;
  // background-color:skyblue;
  display:inline-block;
  vertical-align:text-top;
  // padding:20px;
  .input{
    width:50%;
    // margin:10px;
  }
}
.draggable-right{
  height:300px;
  width:100%;
  overflow-y:auto;
  // width:1000px;
  padding:20px 0;
  border:5px solid hotpink;
}
}
.content-item{
  // display:inline-block;
}
.ff{
  width:50%;
  min-height:200px;
  background:skyblue;
}
</style>

Copy the code