Appearance
ZDrag
通用拖拽组件,对大部分浏览器
支持的同时也支持触屏设备
,对组件样式和内容没有约束,可以自由的发挥创意。
基础用法
绑定一个 data
即可实现拖拽。
<template>
<z-drag class="dragGroup" v-model:data="data"></z-drag>
</template>
<script setup lang="ts">
import type { IDragData } from "@d7ee/z-base-ui/dist/types/components/ZDrag";
import { ref } from "vue";
const data = ref<IDragData[]>([
{ id: "1", name: "语文" },
{ id: "2", name: "数学" },
{ id: "3", name: "体育" },
{ id: "4", name: "英语" },
{ id: "5", name: "美术" },
{ id: "6", name: "思想教育" },
])
</script>
<style lang="less" scoped>
.dragGroup {
display: flex;
flex-wrap: wrap;
grid-gap: 12px;
}
.dragGroup .z-dragGroup_name {
cursor: pointer;
}
</style>
自定义
使用 item
插槽进行内容自定义
<template>
<z-drag class="dragGroup" v-model:data="data">
<template #item="{record}">
<div class="dragGroup-item">
<span class="icon">😊</span>
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
</template>
<script setup lang="ts">
import type { IDragData } from "@d7ee/z-base-ui/dist/types/components/ZDrag";
import { ref } from "vue";
const data = ref<IDragData[]>([
{ id: "1", name: "语文" },
{ id: "2", name: "数学" },
{ id: "3", name: "体育" },
{ id: "4", name: "英语" },
{ id: "5", name: "美术" },
{ id: "6", name: "思想教育" },
])
</script>
<style lang="less" scoped>
.dragGroup {
display: grid;
grid-gap: 12px;
grid-template-columns: repeat(4, 1fr);
}
.dragGroup-item {
cursor: pointer;
display: flex;
align-items: center;
border: 1px solid #c6e2ff;
padding: 3px 6px;
border-radius: 12px;
background-color: #909399;
color: #ffffff;
.icon {
margin-right: 4px;
}
}
</style>
多列表相互拖拽
使用 name
给每个组设置一个ID,列表可以是一个也可以是N个。
<template>
<z-drag class="dragGroup" name="groupA" v-model:data="groupA">
<template #item="{record}">
<div class="dragGroup-item">
<span class="icon">😊</span>
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
<z-drag class="dragGroup" name="groupB" v-model:data="groupB">
<template #item="{record}">
<div class="dragGroup-item">
<span class="icon">🎈</span>
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
<z-drag class="dragGroup" name="groupC" v-model:data="groupC">
<template #item="{record}">
<div class="dragGroup-item">
<span class="icon">😂</span>
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
</template>
<script setup lang="ts">
import type { IDragData } from "@d7ee/z-base-ui/dist/types/components/ZDrag";
import { ref } from "vue";
const groupA = ref<IDragData[]>([
{ id: "1", name: "a-1" },
{ id: "2", name: "a-2" },
{ id: "3", name: "a-3" },
{ id: "4", name: "a-4" },
{ id: "5", name: "a-5" },
])
const groupB = ref<IDragData[]>([
{ id: "b1", name: "b-1" },
{ id: "b2", name: "b-2" },
{ id: "b3", name: "b-3" },
])
const groupC = ref<IDragData[]>([
{ id: "c1", name: "c-1" },
{ id: "c2", name: "c-2" },
])
</script>
<style lang="less" scoped>
.dragGroup {
display: grid;
grid-gap: 12px;
grid-template-columns: repeat(4, 1fr);
padding: 12px;
margin-bottom: 24px;
border: 1px solid #c6e2ff;
}
.dragGroup-item {
cursor: pointer;
display: flex;
align-items: center;
border: 1px solid #c6e2ff;
padding: 3px 6px;
border-radius: 12px;
background-color: #909399;
color: #ffffff;
.icon {
margin-right: 4px;
}
}
</style>
分组拖拽
put
使用put,分组模式下,只能在对应组内进行数据交换
在下面的demo中,A组数据能和B、D就行交换,而B组只能和A组就行交换,C组能和D组交换,而D组能和A、C交换
<template>
<z-drag class="dragGroup" name="groupA" v-model:data="groupA" :put="['groupB', 'groupD']">
<template #item="{record}">
<div class="dragGroup-item">
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
<z-drag class="dragGroup" name="groupB" v-model:data="groupB" :put="['groupA']">
<template #item="{record}">
<div class="dragGroup-item">
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
<z-drag class="dragGroup" name="groupC" v-model:data="groupC" :put="['groupD']">
<template #item="{record}">
<div class="dragGroup-item">
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
<z-drag class="dragGroup" name="groupD" v-model:data="groupD" :put="['groupC', 'groupA']">
<template #item="{record}">
<div class="dragGroup-item">
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
</template>
<script setup lang="ts">
import type { IDragData } from "@d7ee/z-base-ui/dist/types/components/ZDrag";
import { ref } from "vue";
const groupA = ref<IDragData[]>([
{ id: "1", name: "a-1" },
{ id: "2", name: "a-2" },
{ id: "3", name: "a-3" },
{ id: "4", name: "a-4" },
{ id: "5", name: "a-5" },
])
const groupB = ref<IDragData[]>([
{ id: "b1", name: "b-1" },
{ id: "b2", name: "b-2" },
{ id: "b3", name: "b-3" },
])
const groupC = ref<IDragData[]>([
{ id: "c1", name: "c-1" },
{ id: "c2", name: "c-2" },
])
const groupD = ref<IDragData[]>([
{ id: "d1", name: "d-1" },
{ id: "d2", name: "d-2" },
])
</script>
<style lang="less" scoped>
.dragGroup {
display: grid;
grid-gap: 12px;
grid-template-columns: repeat(5, 1fr);
padding: 12px;
margin-bottom: 24px;
border: 1px solid #c6e2ff;
}
.dragGroup-item {
cursor: pointer;
display: flex;
align-items: center;
border: 1px solid #c6e2ff;
padding: 3px 6px;
border-radius: 12px;
background-color: #909399;
color: #ffffff;
.icon {
margin-right: 4px;
}
}
</style>
禁用
使用 disabled
开启禁用模式,disabled
可以针对某项或整体,权重:整体禁用 > 单个禁用
在下面demo中,a组的1和4无法被拖拽,B组整体被禁止拖拽
<template>
<z-drag class="dragGroup" name="groupA" v-model:data="groupA">
<template #item="{record}">
<div class="dragGroup-item">
<span class="icon">😊</span>
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
<z-drag class="dragGroup" name="groupB" disabled v-model:data="groupB">
<template #item="{record}">
<div class="dragGroup-item">
<span class="icon">🎈</span>
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
<z-drag class="dragGroup" name="groupC" v-model:data="groupC">
<template #item="{record}">
<div class="dragGroup-item">
<span class="icon">😂</span>
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
</template>
<script setup lang="ts">
import type { IDragData } from "@d7ee/z-base-ui/dist/types/components/ZDrag";
import { ref } from "vue";
const groupA = ref<IDragData[]>([
{ id: "1", name: "a-1", disabled: true },
{ id: "2", name: "a-2" },
{ id: "3", name: "a-3" },
{ id: "4", name: "a-4", disabled: true },
{ id: "5", name: "a-5" },
])
const groupB = ref<IDragData[]>([
{ id: "b1", name: "b-1" },
{ id: "b2", name: "b-2" },
{ id: "b3", name: "b-3" },
])
const groupC = ref<IDragData[]>([
{ id: "c1", name: "c-1" },
{ id: "c2", name: "c-2" },
])
</script>
<style lang="less" scoped>
.dragGroup {
display: grid;
grid-gap: 12px;
grid-template-columns: repeat(4, 1fr);
padding: 12px;
margin-bottom: 24px;
border: 1px solid #c6e2ff;
}
.dragGroup-item {
cursor: pointer;
display: flex;
align-items: center;
border: 1px solid #c6e2ff;
padding: 3px 6px;
border-radius: 12px;
background-color: #909399;
color: #ffffff;
.icon {
margin-right: 4px;
}
}
</style>
自定义样式
使用 drag-name
自定义一个类名, 通过对class类名的样式覆盖从而实现修改元素被选中后发生拖拽时的样式,您可拖拽下方的元素体验该效果。
<template>
<z-drag class="dragGroup" v-model:data="data" drag-name="customStyle">
<template #item="{record}">
<div class="dragGroup-item">
<span class="icon">😊</span>
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
</template>
<script setup lang="ts">
import type { IDragData } from "@d7ee/z-base-ui/dist/types/components/ZDrag";
import { ref } from "vue";
const data = ref<IDragData[]>([
{ id: "1", name: "语文" },
{ id: "2", name: "数学" },
{ id: "3", name: "体育" },
{ id: "4", name: "英语" },
{ id: "5", name: "美术" },
{ id: "6", name: "思想教育" },
]);
</script>
<style lang="less" scoped>
.dragGroup {
display: grid;
grid-gap: 12px;
grid-template-columns: repeat(4, 1fr);
.customStyle {
.dragGroup-item {
background: linear-gradient(45deg, #b697e8 50%, #6a23df 50%);
}
}
}
.dragGroup-item {
cursor: pointer;
display: flex;
align-items: center;
border: 1px solid #c6e2ff;
padding: 3px 6px;
border-radius: 12px;
background-color: #909399;
color: #ffffff;
.icon {
margin-right: 4px;
}
}
</style>
自定义句柄
使用 handle
定义句柄类名,只有具备该类名的元素才能进行拖动,在下面的demo中,只有鼠标移至😊上才能进行拖动。
<template>
<z-drag class="dragGroup" v-model:data="data" handle="handle" :unselectable="true">
<template #item="{record}">
<div class="dragGroup-item">
<span class="icon handle">😊</span>
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
</template>
<script setup lang="ts">
import type { IDragData } from "@d7ee/z-base-ui/dist/types/components/ZDrag";
import { ref } from "vue";
const data = ref<IDragData[]>([
{ id: "1", name: "语文" },
{ id: "2", name: "数学" },
{ id: "3", name: "体育" },
{ id: "4", name: "英语" },
{ id: "5", name: "美术" },
{ id: "6", name: "思想教育" },
]);
</script>
<style lang="less" scoped>
.dragGroup {
display: grid;
grid-gap: 12px;
grid-template-columns: repeat(4, 1fr);
.customStyle {
.dragGroup-item {
background: linear-gradient(45deg, #b697e8 50%, #6a23df 50%);
}
}
}
.dragGroup-item {
cursor: pointer;
display: flex;
align-items: center;
border: 1px solid #c6e2ff;
padding: 3px 6px;
border-radius: 12px;
background-color: #909399;
color: #ffffff;
.icon {
margin-right: 4px;
}
}
</style>
严格模式
使用 strict
开启严格模式,严格模式是为了防止拖拽项乱串而设计的一个开关,在严格模式下数据从哪来就只能回哪去。
在下面的demo中,数据只能从A,B,C,移动到D,而D内的数据只能原路返回,A组的数据无法被拖到B,C中。
WARNING
注意:该功能仍处于开发和测试中,目前只是一个先行版,存在一个较为致命的缺陷,不能对D组设置默认值,设置默认值后在拖动D组原数据时会出现一些意外的状况。
<template>
<z-drag class="dragGroup" name="groupA" v-model:data="groupA" :put="['groupD']" strict>
<template #item="{record}">
<div class="dragGroup-item">
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
<z-drag class="dragGroup" name="groupB" v-model:data="groupB" :put="['groupD']" strict>
<template #item="{record}">
<div class="dragGroup-item">
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
<z-drag class="dragGroup" name="groupC" v-model:data="groupC" :put="['groupD']" strict>
<template #item="{record}">
<div class="dragGroup-item">
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
<z-drag class="dragGroup" name="groupD" v-model:data="groupD" :put="['groupC', 'groupB', 'groupA']" strict>
<template #item="{record}">
<div class="dragGroup-item">
<span>{{record.name}}</span>
</div>
</template>
</z-drag>
</template>
<script setup lang="ts">
import type { IDragData } from "@d7ee/z-base-ui/dist/types/components/ZDrag";
import { ref } from "vue";
const groupA = ref<IDragData[]>([
{ id: "1", name: "a-1" },
{ id: "2", name: "a-2" },
{ id: "3", name: "a-3" },
{ id: "4", name: "a-4" },
{ id: "5", name: "a-5" },
])
const groupB = ref<IDragData[]>([
{ id: "b1", name: "b-1" },
{ id: "b2", name: "b-2" },
{ id: "b3", name: "b-3" },
])
const groupC = ref<IDragData[]>([
{ id: "c1", name: "c-1" },
{ id: "c2", name: "c-2" },
])
const groupD = ref<IDragData[]>([
{ id: "d1", name: "d-1", disabled: true },
])
</script>
<style lang="less" scoped>
.dragGroup {
display: grid;
grid-gap: 12px;
grid-template-columns: repeat(5, 1fr);
padding: 12px;
margin-bottom: 24px;
border: 1px solid #c6e2ff;
}
.dragGroup-item {
cursor: pointer;
display: flex;
align-items: center;
border: 1px solid #c6e2ff;
padding: 3px 6px;
border-radius: 12px;
background-color: #909399;
color: #ffffff;
.icon {
margin-right: 4px;
}
}
</style>
API 属性
属性名 | 说明 | 类型 | 默认值 |
---|---|---|---|
data | 数据源,通过v-model 绑定,数据格式详见IDragData | IDragData[] | [] |
name | 组名称类似于唯一ID,需要多列表互相拖拽时需设置该值,详见多列表互相拖拽 | string | — |
sort | 禁用排序,禁用后当前组无法拖拽排序 | boolean | false |
put | 是否允许其它元素被拖拽进当前组,为true时允许其它组拖拽元素进入,false则禁止,string[]时可约束那些组能将元素拖拽到当前元素,string来源于name,详见分组拖拽 | boolean | string[] | true |
pull | 移出设置,true时允许当前组内元素被拖拽到其它组,false时则禁止移出 | boolean | true |
strict | 严格模式,约束数据类型,从哪来就只能回哪去,详见严格模式 | boolean | false |
disabled | 禁用,禁用后当前组内的元素无法被拖拽,详见禁用 | boolean | false |
dragName | 元素被拖拽时的类名,详见自定义样式 | string | — |
handle | 句柄,定义可被拖拽的元素类名,详见自定义句柄 | string | — |
unselectable | 禁止用户选中内容,详见自定义句柄 | boolean | false |
slot 插槽
通过插槽可接收一个record参数,参数类型详见类型声明
slotName | 说明 | 参数 |
---|---|---|
item | 用于自定义内容 | {record: IDragData} |
Vue
<z-drag class="dragGroup" v-model:data="data">
<template #item="{record}">
自定义内容
</template>
</z-drag>
event 事件
各事参数类型详见类型声明
事件名称 | 说明 | 回调参数 |
---|---|---|
onStart | 开始拖拽时回调 | (event: any) => void |
onEnd | 拖拽结束时回调 | (event: any) => void |
onAdd | 其它元素移动到当前组后回调 | (event: IZDragOnAdd) => void |
onRemove | 元素从 当前组移动到其它组后回调 | (event: IZDragOnRemove) => void |
update:data | 数据发生改变时通过v-mode:data更新绑定的变量 |
TS类型
IDragData
typescript
interface IDragData {
// ID
id: string;
// 名称
name: string;
// 禁用拖拽
disabled?: boolean;
// 拓展属性,可自定义其它字段
expand?: Record<string, any>;
}
IZDragOnAdd
typescript
interface IZDragOnAdd {
// 数据项
data: IDragData,
// 原组所在下标
formIndex: number,
// 当前组内所在下标
toIndex: number
}
IZDragOnRemove
typescript
interface IZDragOnRemove {
// 数据项
data: IDragData,
// 下标
index: number
}