1. 程式人生 > 實用技巧 >vuedraggable 拖拽元件 封裝

vuedraggable 拖拽元件 封裝

demo:

<template>
  <div class="fluid container">
    <div class="form-group form-group-lg panel panel-default">
      <div class="panel-heading">
        <h3 class="panel-title">拖拽元件</h3>
      </div>
      <div class="panel-body">
        <div class
="checkbox"> <label><input type="checkbox" v-model="editable">啟用拖拽</label> </div> <button type="button" class="btn btn-default" @click="orderList">恢復初始排序</button> </div> </div> <div class="box"> <div
class="groupBox"> <div class="col-md-3"> <!-- 拖拽元素盒子 --> <draggable class="list-group" element="ul" v-model="list" :options="dragOptions" :move="onMove" @start="isDragging=true" @end="isDragging=false"> <transition-group
type="transition" :name="'flip-list'"> <li class="list-group-item licommon" v-for="element in list" :key="element.order"> <i :class="element.fixed? 'fa fa-anchor' : 'glyphicon glyphicon-pushpin'" @click=" element.fixed=! element.fixed" aria-hidden="true"></i> {{element.name}} <span class="badge">{{element.order}}</span> </li> </transition-group> </draggable> </div> </div> <div class="groupBox"> <div class="col-md-3"> <!-- 目標元素盒子 --> <draggable element="span" v-model="list2" :options="dragOptions" :move="onMove"> <transition-group name="no" class="list-group targetUl" tag="ul"> <li class="list-group-item" v-for="element in list2" :key="element.order"> <i :class="element.fixed? 'fa fa-anchor' : 'glyphicon glyphicon-pushpin'" @click=" element.fixed=! element.fixed" aria-hidden="true"></i> {{element.name}} <span class="badge">{{element.order}}</span> </li> </transition-group> </draggable> </div> </div> </div> <div class="arr"> <!-- 拖拽陣列 --> <div class="list-group col-md-3 arrcommon"> <pre>{{listString}}</pre> </div> <!-- 目標陣列 --> <div class="list-group col-md-3 arrcommon"> <pre>{{list2String}}</pre> </div> </div> </div> </template> <script> import draggable from "vuedraggable"; const message = [ "詹姆斯", "杜蘭特", "科比", "喬丹" ]; export default { name: "hello", components: { draggable }, data() { return { list: message.map((name, index) => { return { name, order: index + 1, fixed: false }; }), list2: [], editable: true, isDragging: false, delayedDragging: false }; }, methods: { // 恢復初始排序,已經有拖拽到右邊時無法恢復 orderList() { this.list = this.list.sort((one, two) => { return one.order - two.order; }); }, onMove({ relatedContext, draggedContext }) { // 關聯元素 const relatedElement = relatedContext.element; // 拖拽元素 const draggedElement = draggedContext.element; console.log('拖拽1', relatedElement) console.log('拖拽2', draggedElement) return ( (!relatedElement || !relatedElement.fixed) && !draggedElement.fixed ); } }, computed: { // 配置項 dragOptions() { return { animation: 0, group: "description", disabled: !this.editable, ghostClass: "ghost" }; }, listString() { return JSON.stringify(this.list, null, 2); }, list2String() { return JSON.stringify(this.list2, null, 2); } }, watch: { isDragging(newValue) { if (newValue) { this.delayedDragging = true; return; } this.$nextTick(() => { this.delayedDragging = false; }); } } }; </script> <style> .box{ display:flex; } .arr{ display:flex; } .arr .arrcommon{ width:50%; border:1px solid red; } .targetUl{ display:flex; } .groupBox{ border:1px solid #00FFFF; width:50%; } .groupBox li{ list-style: none; height:30px; border:1px solid #eeeeee; } .flip-list-move { transition: transform 0.5s; } .no-move { transition: transform 0s; } .ghost { opacity: 0.5; background: #c8ebfb; } .list-group { min-height: 20px; } .list-group-item { cursor: move; } .list-group-item i { cursor: pointer; } </style>
View Code

封裝後的元件程式碼:

<template>
  <div class="board-column">
    <div class="board-column-header">
      {{ headerText }}
    </div>
    <draggable
      :list="list"
      v-bind="$attrs"
      class="board-column-content"
      :set-data="setData"
    >
      <div v-for="element in list" :key="element.id" class="board-item">
        {{ element.name }} {{ element.id }}
      </div>
    </draggable>
  </div>
</template>

<script>
import draggable from "vuedraggable";
export default {
  name: "DragKanbanDemo",
  components: {
    draggable,
  },
  props: {
    headerText: {
      type: String,
      default: "Header",
    },
    options: {
      type: Object,
      default() {
        return {};
      },
    },
    list: {
      type: Array,
      default() {
        return [];
      },
    },
  },
  methods: {
    setData(dataTransfer) {
      // to avoid Firefox bug
      // Detail see : https://github.com/RubaXa/Sortable/issues/1012
      dataTransfer.setData("Text", "");
    },
  },
};
</script>
<style lang="less" 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 transparent;
    min-height: 60px;
    display: flex;
    justify-content: flex-start;
    flex-direction: column;
    align-items: center;
    .board-item {
      cursor: pointer;
      width: 100%;
      height: 64px;
      margin: 5px 0;
      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);
    }
  }
}
</style>
View Code

使用封裝後的元件:

<template>
  <div class="components-container board">
    <div class="panel-body">
        <div class="checkbox">
          <label><input type="checkbox" v-model="editable" />啟用拖拽</label>
        </div>
    </div>

    <Kanban :key="1" :list="list1" :group="group" :disabled="!this.editable" class="kanban todo" header-text="Todo" />
    <Kanban :key="2" :list="list2" :group="group" :disabled="!this.editable" class="kanban working" header-text="Working" />
    <Kanban :key="3" :list="list3" :group="group" :disabled="!this.editable" class="kanban done" header-text="Done" />
  </div>
</template>
<script>
import Kanban from '@/components/Kanban'
export default {
  name: 'DragKanbanDemo',
  components: {
    Kanban
  },
  data() {
    return {
      editable: true,
      group: 'mission',
      list1: [
        { name: 'Mission', id: 1 },
        { name: 'Mission', id: 2 },
        { name: 'Mission', id: 3 },
        { name: 'Mission', id: 4 }
      ],
      list2: [
        { name: 'Mission', id: 5 },
        { name: 'Mission', id: 6 },
        { name: 'Mission', id: 7 }
      ],
      list3: [
        { name: 'Mission', id: 8 },
        { name: 'Mission', id: 9 },
        { name: 'Mission', id: 10 }
      ]
    }
  },
}
</script>
<style lang="less">
.board {
  width: 1000px;
  margin-left: 20px;
  display: flex;
  justify-content: space-around;
  flex-direction: row;
  align-items: flex-start;
}
.kanban {
  &.todo {
    .board-column-header {
      background: #4A9FF9;
    }
  }
  &.working {
    .board-column-header {
      background: #f9944a;
    }
  }
  &.done {
    .board-column-header {
      background: #2ac06d;
    }
  }
}
</style>
View Code