To-Do Calendar - Day10 用 Vue Draggable 實作拖曳效果
花了幾天終於把所有內頁、Modal 和前端效果都做完了~這次要介紹的是用 Vue Draggable 來完成拖曳排序功能。
載入 Vue Draggable
Vue.Draggable 是一款基於 Sortable.js 實現的 vue 拖曳套件,支援移動裝置拖拽(支持觸摸設備),可以在不同列表間拖拽,支援 vue 2 過渡動畫相容,官網有很詳細的文檔以及充足的代碼例子,上手容易,是一款非常優秀的 vue 拖拽元件。
-
安裝 Vue Draggable
Warning此專案用的是 Vue 2,所以安裝的是對應的 Vue.Draggable 版本。npm install vuedraggable@2.20.0 --save
-
在需要使用拖拽的組件載入並註冊後,就可以使用了
<script> import draggable from "vuedraggable"; export default { components: { draggable }, ...
-
在要使用拖曳功能的列表外層用
<draggable>
包起來,並綁定 v-model<template> <main> <div> <draggable v-model="list"> <div v-for="item in list" :key="item.id"> <h1 class="text-center">{{ item.name }}</h1> </div> </draggable> </div> </main> </template> <script> import draggable from "vuedraggable"; export default { components: { draggable, }, data() { return { list: [ { name: "John", id: 0 }, { name: "Joao", id: 1 }, { name: "Jean", id: 2 }, ], }; }, }; </script>
-
運行開發環境,測試 draggable 是否運作
最基本的拖曳效果出來了!
draggable 屬性
可以使用 v-bind 屬性作為配置項或直接寫在 <draggable>
,以下列出專案中較常使用到的屬性,其他屬性可參考 vue.draggable 中文文檔
- group:用於分組,同一組的不同 list 可以相互拖曳
- delay:鼠標選中列表單元可以開始拖動的延遲時間
- disabled:是否啟用拖曳功能
- animation:拖曳動畫時間長度(毫秒),搭配
<transition-group>
使用 - chosenClass:設定被選中目標的樣式
draggable 事件
- start(evt):開始拖拽時候觸發
- add(evt):拖拽新增的時候觸發
- remove(evt):從列表拖走,移除觸發
- update(evt):列表更新觸發
- end(evt):拖拽完成時觸發
- choose(evt):選擇拖拽元素觸發
- sort(evt):排序觸發
- change(evt):如果數據不是整個提交,單個提交數據的時候就會用到它
實作原子習慣分頁拖曳功能
- habitTracker.vue(單個列表)
... <draggable v-model="habitList" v-bind="dragOptions" @start="drag = true" @end="drag = false" :move="getdata" @update="datadragEnd" class="list-group" > <transition-group type="transition" name="!drag ? 'flip-list' : null" > <li v-for="item in habitList" ... > {{ item.name }} ... </li> </transition-group> </draggable>
import draggable from "vuedraggable"; export default { components: { draggable }, data() { return { habitList: [ { id: "1", name: "吃早餐", checkColor: "red" }, { id: "2", name: "喝水2000cc", checkColor: "yellow" }, { id: "3", name: "寫技術部落格", checkColor: "green" }, { id: "4", name: "伸展10分鐘", checkColor: "teal" }, { id: "5", name: "睡前保養", checkColor: "blue" }, { id: "6", name: "12點前就寢", checkColor: "pink" }, { id: "7", name: "戴維持器", checkColor: "pink" }, ], }; }, computed: { dragOptions() { return { animation: 300, disabled: false, chosenClass:"chosen", }; }, },
實作代辦事項分頁拖曳功能
- 設定 group 讓不同列表的單元可以互相拖曳
- todoLists.vue(2個列表)
... <draggable v-model="todoList" v-bind="dragOptions" @start="drag = true" @end="drag = false" :move="getdata" @update="datadragEnd" class="list-group" > <transition-group type="transition" name="!drag ? 'flip-list' : null" > <div v-for="item in todoList" ... {{ item.name }} ... </div> </transition-group> </draggable>
... <draggable v-model="doneList" v-bind="dragOptions" @start="drag = true" @end="drag = false" :move="getdata" @update="datadragEnd" class="list-group" > <transition-group type="transition" name="!drag ? 'flip-list' : null" > <div v-for="item in doneList" ... {{ item.name }} ... </div> </transition-group> </draggable>
import draggable from "vuedraggable"; export default { components: { draggable }, data() { return { todoList: [ { id: "TA01", name: "代辦事項1", labelType: "firstColor" }, { id: "TA02", name: "代辦事項2", labelType: "secondColor" }, { id: "TA03", name: "代辦事項3", labelType: "thirdColor" }, { id: "TA04", name: "代辦事項4", labelType: "fourthColor" }, ], doneList: [ { id: "TA01", name: "完成事項1", labelType: "firstColor" }, { id: "TA02", name: "完成事項2", labelType: "secondColor" }, { id: "TA03", name: "完成事項3", labelType: "thirdColor" }, { id: "TA04", name: "完成事項4", labelType: "fourthColor" }, ], }; }, computed: { dragOptions() { return { animation: 300, group: "task", disabled: false, chosenClass: "chosen", }; }, },
實作便條貼牆分頁拖曳功能
- 設定 group 讓不同列表的單元可以互相拖曳
- notes.vue(4個列表)
... <draggable v-model="list1" v-bind="dragOptions" @start="drag = true" @end="drag = false" :move="getdata" @update="datadragEnd" class="list-group" > <transition-group type="transition" name="!drag ? 'flip-list' : null" > <div v-for="item in list1" ... {{ item.name }} ... </div> </transition-group> </draggable>
... <draggable v-model="list2" v-bind="dragOptions" @start="drag = true" @end="drag = false" :move="getdata" @update="datadragEnd" class="list-group" > <transition-group type="transition" name="!drag ? 'flip-list' : null" > <div v-for="item in list2" ... {{ item.name }} ... </div> </transition-group> </draggable>
... <draggable v-model="list3" v-bind="dragOptions" @start="drag = true" @end="drag = false" :move="getdata" @update="datadragEnd" class="list-group" > <transition-group type="transition" name="!drag ? 'flip-list' : null" > <div v-for="item in list3" ... {{ item.name }} ... </div> </transition-group> </draggable>
... <draggable v-model="list4" v-bind="dragOptions" @start="drag = true" @end="drag = false" :move="getdata" @update="datadragEnd" class="list-group" > <transition-group type="transition" name="!drag ? 'flip-list' : null" > <div v-for="item in list4" ... {{ item.name }} ... </div> </transition-group> </draggable>
import draggable from "vuedraggable"; export default { components: { draggable }, data() { return { list1: [ { id: "N01", name: "title1", content: "aaa", bgColor: "#f7e3cb", tapeStyle: "06", }, { id: "N05", name: "title5", content: "eee", bgColor: "#d7ebf4", tapeStyle: "04", }, ], list2: [ { id: "N02", name: "title2", content: "bbb", bgColor: "#ddeee8", tapeStyle: "02", }, { id: "N07", name: "title7", content: "fff", bgColor: "#e7d4e8", tapeStyle: "05", }, ], list3: [ { id: "N03", name: "title3", content: "ccc", bgColor: "#f6d8e4", tapeStyle: "03", }, { id: "N08", name: "title8", content: "fff", bgColor: "#d7ebf4", tapeStyle: "01", }, ], list4: [ { id: "N04", name: "title4", content: "ddd", bgColor: "#fff8b7", tapeStyle: "04", }, { id: "N06", name: "title6", content: "ddd", bgColor: "#ddeee8", tapeStyle: "02", }, ], }; }, computed: { dragOptions() { return { animation: 300, group: "note", disabled: false, chosenClass: "chosen", }; }, },