大家好,我是 simple ,我的理想是
利用科技手段来解决生活中遇到的各种问题
。
vuedraggable
vue-draggable 使用 Vue.js 的组件来实现拖放(拖动)效果。vue2和vue3在使用方面的区别不大,能区分的我都尽可能做了标注,所以就不分两篇文章了。
npm install vuedraggable --save
npm install vuedraggable@next --save
yarn add vuedraggable
yarn add vuedraggable@next
基本用法只需要在 Vue 项目中导入vuedraggable
组件并注册即可:
import draggable from 'vuedraggable'
export default {
components: {
draggable
然后在模板中使用它:
<draggable v-model="list">
<div v-for="element in list" class="list-element">{{element}}</div>
</draggable>
.list-element {
padding: 10px;
background: #eee;
data: {
list: ['Item 1', 'Item 2', 'Item 3']
这将使这些列表项可拖拽排序。
<template>
<div class="row">
<div class="col-2">
<div class="form-group">
class="btn-group-vertical buttons"
role="group"
aria-label="Basic example"
<button class="btn btn-secondary" @click="add">Add</button>
<button class="btn btn-secondary" @click="replace">Replace</button>
</div>
<div class="form-check">
<input
id="disabled"
type="checkbox"
v-model="enabled"
class="form-check-input"
<label class="form-check-label" for="disabled">DnD enabled</label>
</div>
</div>
</div>
<div class="col-6">
<h3>Draggable {{ draggingInfo }}</h3>
<draggable
:list="list"
:disabled="!enabled"
class="list-group"
ghost-class="ghost"
:move="checkMove"
@start="dragging = true"
@end="dragging = false"
class="list-group-item"
v-for="element in list"
:key="element.name"
{{ element.name }}
</div>
</draggable>
</div>
<rawDisplayer class="col-3" :value="list" title="List" />
</div>
</template>
<script>
import draggable from "@/vuedraggable";
let id = 1;
export default {
name: "simple",
display: "Simple",
order: 0,
components: {
draggable
data() {
return {
enabled: true,
list: [
{ name: "John", id: 0 },
{ name: "Joao", id: 1 },
{ name: "Jean", id: 2 }
dragging: false
computed: {
draggingInfo() {
return this.dragging ? "under drag" : "";
methods: {
add: function() {
this.list.push({ name: "Juan " + id, id: id++ });
replace: function() {
this.list = [{ name: "Edgard", id: id++ }];
checkMove: function(e) {
window.console.log("Future index: " + e.draggedContext.futureIndex);
</script>
<style scoped>
.buttons {
margin-top: 35px;
.ghost {
opacity: 0.5;
background: #c8ebfb;
</style>
<template>
<div class="row">
<div class="col-3">
<h3>Draggable 1</h3>
<draggable
class="list-group"
:list="list1"
group="people"
@change="log"
itemKey="name"
<template #item="{ element, index }">
<div class="list-group-item">{{ element.name }} {{ index }}</div>
</template>
</draggable>
</div>
<div class="col-3">
<h3>Draggable 2</h3>
<draggable
class="list-group"
:list="list2"
group="people"
@change="log"
itemKey="name"
<template #item="{ element, index }">
<div class="list-group-item">{{ element.name }} {{ index }}</div>
</template>
</draggable>
</div>
<rawDisplayer class="col-3" :value="list1" title="List 1" />
<rawDisplayer class="col-3" :value="list2" title="List 2" />
</div>
</template>
<script>
import draggable from "@/vuedraggable";
export default {
name: "two-lists",
display: "Two Lists",
order: 1,
components: {
draggable
data() {
return {
list1: [
{ name: "John", id: 1 },
{ name: "Joao", id: 2 },
{ name: "Jean", id: 3 },
{ name: "Gerard", id: 4 }
list2: [
{ name: "Juan", id: 5 },
{ name: "Edgard", id: 6 },
{ name: "Johnson", id: 7 }
methods: {
add: function() {
this.list.push({ name: "Juan" });
replace: function() {
this.list = [{ name: "Edgard" }];
clone: function(el) {
return {
name: el.name + " cloned"
log: function(evt) {
window.console.log(evt);
</script>
<template>
<div class="row">
<div class="col-8">
<h3>Draggable table</h3>
<table class="table table-striped">
<thead class="thead-dark">
<th scope="col">Id</th>
<th scope="col">Name</th>
<th scope="col">Sport</th>
</thead>
<draggable v-model="list" tag="tbody" item-key="name">
<template #item="{ element }">
<td scope="row">{{ element.id }}</td>
<td>{{ element.name }}</td>
<td>{{ element.sport }}</td>
</template>
</draggable>
</table>
</div>
<rawDisplayer class="col-3" :value="list" title="List" />
</div>
</template>
<script>
import draggable from "@/vuedraggable";
export default {
name: "table-example",
display: "Table",
order: 8,
components: {
draggable
data() {
return {
list: [
{ id: 1, name: "Abby", sport: "basket" },
{ id: 2, name: "Brooke", sport: "foot" },
{ id: 3, name: "Courtenay", sport: "volley" },
{ id: 4, name: "David", sport: "rugby" }
dragging: false
</script>
<style scoped>
.buttons {
margin-top: 35px;
</style>
Props
value(vue2) 或 modelValue(vue3)
type:Array
require:false
default:null
输入要拖动的组件数组。通常与内部元素v-for指令引用的相同数组。
<draggable v-model="myArray">
type:Array
require:false
default:null
value
属性的替代方案,list是一个与拖放同步的数组。
主要区别是list
属性使用splice方法更新数组,而value
是不可变的。
不要与value
属性一起使用。
type:String
require:false
default:'div'
draggable组件作为外部元素创建的HTML节点类型,用于包含的插槽。
也可以将Vue组件的名称作为元素传递。在这种情况下,draggable属性将传递给创建的组件。
如果需要为创建的组件设置props或事件,请参见下面的componentData。示例:
<draggable tag="ul">
<li>...</li>
</draggable>
这将渲染:
<li>...</li>
而不是默认的div
。也可以传入组件:
<draggable tag="todo-list">
<todo-item v-for="item in list" :text="item.text" />
</draggable>
这将渲染todo-list
组件,并将draggable
prop传递给它。
clone
type:Function
require:false
default:(original) => { return original;}
当clone选项为true时,在源组件上调用以克隆元素的函数。唯一的参数是要克隆的viewModel元素,返回值是其克隆版本。
默认情况下,vue.draggable重用viewModel元素,所以如果要克隆或深度克隆它,必须使用这个钩子。示例:
clone: (original) => {
let clone = JSON.parse(JSON.stringify(original))
return clone
这将在拖动操作期间深度克隆元素,而不是重新使用原始元素。你可以在这里执行任何自定义克隆逻辑。如果不提供clone
prop,vue.draggable
将简单地重新使用元素,而不是实际克隆它。所以,如果你的元素是Vue实例,或者您需要对其进行深度克隆,则必须提供clone
prop。
type:Function
require:false
default:null
如果不为null,这个函数将以类似的方式调用Sortable onMove回调。返回false将取消拖动操作。
HTML:
<draggable :list="list" :move="checkMove">
javascript:
checkMove: function(evt){
return (evt.draggedContext.element.name!=='apple');
componentData
type:Object
require:false
default:null
这个道具用于向通过声明的子组件传递额外信息。
• props
: 要传递给子组件的道具
• attrs
: 要传递给子组件的属性
• on
: 要在子组件中订阅的事件
<draggable tag="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
attrs:{
wrap: true
props: {
value: this.activeNames
componentData
prop允许您将props,attrs和on传递给tag
prop声明的子组件。这使您可以完全控制子组件及其与父组件draggable
的交互。
其他sortable参数
从vue.draggable的版本2.19开始,可以直接将Sortable选项设置为vue.draggable的props。
group: "name",
sort: true,
delay: 0,
delayOnTouchOnly: false,
touchStartThreshold: 0,
disabled: false,
store: null,
animation: 150,
easing: "cubic-bezier(1, 0, 0, 1)",
handle: ".my-handle",
filter: ".ignore-elements",
preventOnFilter: true,
draggable: ".item",
chosenClass: "sortable-chosen",
dragClass: "sortable-drag",
invertSwap: false,
invertedSwapThreshold: 1,
direction: 'horizontal',
fallbackClass: "sortable-fallback",
fallbackOnBody: false,
fallbackTolerance: 0,
removeCloneOnHide: true,
emptyInsertThreshold: 5,
支持kebab-case属性。例如,ghost-class
属性将转换为ghostClass
Sortable选项。
设置handle,sortable和group选项的示例:
<draggable
v-model="list"
handle=".handle"
group="name"
ghost-class="ghost"
:sort="false"
@change="log"
</draggable>
EVENT
• 支持Sortable事件:
• start
, add
, remove
, update
, end
, choose
, unchoose
, sort
, filter
, clone
• 在Sortable.js触发onStart, onAdd, onRemove, onUpdate, onEnd, onChoose, onUnchoose, onSort, onClone时,events将以相同的参数进行调用。
HTML:
<draggable :list="list" @end="onEnd">
change
事件 当list prop不为空并且相应的数组因拖放操作而改变时,将触发change
事件。此事件将以一个参数调用,其中包含以下属性之一:
added
: 包含添加到数组中的元素的信息
newIndex
: 添加的元素的索引
element
: 添加的元素
removed
: 包含从数组中移除的元素的信息
oldIndex
: 移除之前元素的索引
element
: 被移除的元素
moved
: 包含在数组中移动的元素的信息
newIndex
: 移动的元素的当前索引
oldIndex
: 移动的元素的旧索引
element
: 移动的元素change
事件在list
prop发生变化时触发,并提供有关添加,删除或移动元素的详细信息。这使您可以在数组因拖放操作而改变时执行自定义逻辑。
vue2限制:header或footer插槽无法与transition-group一起使用。
Header
使用header
插槽在vuedraggable组件内添加不可拖动元素。
重要提示:它应与draggable选项一起使用来标记可拖动元素。请注意,header插槽将始终位于默认插槽之前,而不考虑其在模板中的位置。例如:
<draggable v-model="myArray" draggable=".item">
<div v-for="element in myArray" :key="element.id" class="item">
{{element.name}}
</div>
<button slot="header" @click="addPeople">Add</button>
</draggable>
Footer
使用footer
插槽在vuedraggable组件内添加不可拖动元素。重要提示:它应与draggable选项一起使用来标记可拖动元素。请注意,footer插槽将始终位于默认插槽之后,而不考虑其在模板中的位置。例如:
<draggable v-model="myArray" draggable=".item">
<div v-for="element in myArray" :key="element.id" class="item">
{{element.name}}
</div>
<button slot="footer" @click="addPeople">Add</button>
</draggable>
从vue 2版本迁移:
使用item
插槽代替默认插槽来显示元素
使用itemKey
道具为项目提供键
<draggable v-model="myArray">
<div v-for="element in myArray" :key="element.id">{{element.name}}</div>
</draggable>
<draggable v-model="myArray" item-key="id">
<template #item="{element}">
<div>{{element.name}}</div>
</template>
</draggable>
使用过渡时,现在应使用tag
道具和componentData
来创建过渡
<draggable v-model="myArray">
<transition-group name="fade">
<div v-for="element in myArray" :key="element.id">
{{element.name}}
</div>
</transition-group>
</draggable>
<draggable v-model="myArray" tag="transition-group" :component-data="{name:'fade'}">
<template #item="{element}">
<div>{{element.name}}</div>
</template>
</draggable>
simple_lau
前端 @搬砖师傅
粉丝