1. 程式人生 > 實用技巧 >Draggable為基於Sortable.js的vue元件,用以實現拖拽功能。

Draggable為基於Sortable.js的vue元件,用以實現拖拽功能。

特性

支援觸控裝置
支援拖拽和選擇文字
支援智慧滾動
支援不同列表之間的拖拽
不以jQuery為基礎
和檢視模型同步重新整理
和vue2的國度動畫相容
支援撤銷操作
當需要完全控制時,可以丟擲所有變化
可以和現有的UI元件相容

安裝

npm install vuedraggable

引入

import draggable from 'vuedraggable'

官方例子:
hello.vue

<template>
  <div class="fluid container">
    <div class="form-group form-group-lg panel panel-default
"> <div class="panel-heading"> <h3 class="panel-title">Sortable control</h3> </div> <div class="panel-body"> <div class="checkbox"> <label><input type="checkbox" v-model="editable">Enable drag and drop</label> </div> <button type="
button" class="btn btn-default" @click="orderList">Sort by original order</button> </div> </div> <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" 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 class="col-md-3"> <draggable element="span" v-model="list2" :options="dragOptions" :move="onMove"> <transition-group name="no" class="list-group" 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 class="list-group col-md-3"> <pre>{{listString}}</pre> </div> <div class="list-group col-md-3"> <pre>{{list2String}}</pre> </div> </div> </template> <script> import draggable from "vuedraggable"; const message = [ "vue.draggable", "draggable", "component", "for", "vue.js 2.0", "based", "on", "Sortablejs" ]; 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; 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> .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>

main.js

import Vue from "vue";
import App from "./App.vue";
import "bootstrap/dist/css/bootstrap.css";
import "font-awesome/less/font-awesome.less";

Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

屬性和方法說明

屬性

value

Array,非必須,預設為null

用於實現拖拽的list,通常和內部v-for迴圈的陣列為同一陣列。
最好使用vuex來實現傳入。
不是直接使用,而是通過v-model引入。

<draggable v-model="myArray">

list

Array,非必須,預設為null

就是value的替代品。
和v-model不能共用
從表現上沒有看出不同

element

String,預設div

就是<draggable>標籤在渲染後展現出來的標籤型別
也是包含拖動列表和插槽的外部標籤
可以用來相容UI元件

options

Object

配置項
group: string or array 分組用的,同一組的不同list可以相互拖動
sort: boolean 定義是否可以拖拽
delay:number 定義滑鼠選中列表單元可以開始拖動的延遲時間
touchStartThreshold:number (不清楚)
disabled: boolean 定義是否此sortable物件是否可用,為true時sortable物件不能拖放排序等功能
store:
animation: umber 單位:ms 動畫時間
handle: selector 格式為簡單css選擇器的字串,使列表單元中符合選擇器的元素成為拖動的手柄,只有按住拖動手柄才能使列表單元進行拖動
filter: selector 格式為簡單css選擇器的字串,定義哪些列表單元不能進行拖放,可設定為多個選擇器,中間用“,”分隔
preventOnFilter: 當拖動filter時是否觸發event.preventDefault()預設觸發
draggable: selector 格式為簡單css選擇器的字串,定義哪些列表單元可以進行拖放
ghostClass: selector 格式為簡單css選擇器的字串,當拖動列表單元時會生成一個副本作為影子單元來模擬被拖動單元排序的情況,此配置項就是來給這個影子單元新增一個class,我們可以通過這種方式來給影子元素進行編輯樣式
chosenClass: selector 格式為簡單css選擇器的字串,目標被選中時新增
dragClass:selector 格式為簡單css選擇器的字串,目標拖動過程中新增
forceFallback: boolean 如果設定為true時,將不使用原生的html5的拖放,可以修改一些拖放中元素的樣式等
fallbackClass: string 當forceFallback設定為true時,拖放過程中滑鼠附著單元的樣式
dataIdAttr: data-id
scroll:boolean當排序的容器是個可滾動的區域,拖放可以引起區域滾動
scrollFn:function(offsetX, offsetY, originalEvent, touchEvt, hoverTargetEl) { … } 用於自定義滾動條的適配
scrollSensitivity: number 就是滑鼠靠近邊緣多遠開始滾動預設30
scrollSpeed: number 滾動速度

函式配置

setData: 設定值時的回撥函式
onChoose: 選擇單元時的回撥函式
onStart: 開始拖動時的回撥函式
onEnd: 拖動結束時的回撥函式
onAdd: 新增單元時的回撥函式
onUpdate: 排序發生變化時的回撥函式
onRemove: 單元被移動到另一個列表時的回撥函式
onFilter: 嘗試選擇一個被filter過濾的單元的回撥函式
onMove: 移動單元時的回撥函式
onClone: clone時的回撥函式
以上函式物件的屬性:
to: 移動到的列表的容器
from:來源列表容器
item: 被移動的單元
clone: 副本的單元
oldIndex:移動前的序號
newIndex:移動後的序號

clone

function,預設值: 無處理

這一項要配合著options的group項的pull項處理,當pull:'clone時的拖拽的回撥函式’
就是克隆的意思。
可以理解為正常的拖拽變成了複製。
當為true時克隆

move

function,預設值:null

就是拖拽項時呼叫的函式
用來確定拖拽是否生效
返回null時可以生效
可以通過函式判斷
有一個引數:evt
evt為object
draggedContext: 被拖拽元素的上下文
index:拖拽元素的指標
element: 拖拽資料本身
futureIndex: 拖動後的index
relatedContext: 拖入區域的上下文
index: 目標元素的index
element:目標資料本身
list: 拖入的列表
component:目標元件

<draggable element="ul" v-model="list" :move='allow'>
...
methods: {
  allow(evt) {
    console.log(evt.draggedContext.index)
    console.log(evt.draggedContext.element)
    console.log(evt.draggedContext.futureIndex)
    console.log(evt.relatedContext.index)
    console.log(evt.relatedContext.element)
    console.log(evt.relatedContext.list)
    console.log(evt.relatedContext.component)
    return (evt.draggedContext.element.name!== 'b')
  }
}

componentData

Object,預設值:null

用來結合UI元件的,可以理解為代理了UI元件的定製資訊
包含兩項:props和on
props用來代理UI元件需要繫結的屬性(:)
on用來代理UI元件需要繫結的事件(@)

<draggable element="el-collapse" :list="list" :component-data="getComponentData()">
  <el-collapse-item v-for="e in list" :title="e.title" :name="e.name" :key="e.name">
    <div>{{e.description}}</div>
   </el-collapse-item>
</draggable>

methods: {
  handleChange() {
    console.log('changed');
  },
  inputChanged(value) {
    this.activeNames = value;
  },
  getComponentData() {
    return {
      on: {
        change: this.handleChange,
        input: this.inputChanged
      },
      props: {
        value: this.activeNames
      }
    };
  }
}

事件

有以下幾種
start, add, remove, update, end, choose, sort, filter, clone

引數帶有如下屬性:

add: 包含被新增到列表的元素
newIndex: 新增後的新索引
element: 被新增的元素
removed: 從列表中移除的元素
oldIndex: 移除前的索引
element: 被移除的元素
moved:內部移動的
newIndex: 改變後的索引
oldIndex: 改變前的索引
element: 被移動的元素
插槽
提供一個footer插槽,在排序列表之下。
永遠位於最下方。