一、基本概念
拖拽組件是指用戶可以用鼠標拖動DOM元素,並釋放到指定位置的交互式UI組件。Vue3中新增了一組鉤子,使得我們可以輕鬆地實現拖拽組件的邏輯,這些鉤子包括:
- onDragstart – 拖拽開始時觸發
- onDrag – 拖拽時觸發
- onDragend – 拖拽結束時觸發
- onDrop – 將一個元素拖拽到另一個元素時觸發
在Vue3中,我們可以通過直接給DOM元素添加這些事件的監聽函數來實現拖拽功能。
二、基本用法
下面是一個基本的拖拽組件的代碼示例:
<template>
<div
class="drag-item"
draggable="true"
@dragstart="onDragStart"
@drag="onDrag"
@dragend="onDragEnd">
Drag Me!
</div>
</template>
<script>
export default {
methods: {
onDragStart(event) {
event.dataTransfer.setData('text/plain', 'Drag Me!');
event.target.style.opacity = '0.4';
},
onDrag(event) {
event.target.style.left = `${event.clientX}px`;
event.target.style.top = `${event.clientY}px`;
},
onDragEnd(event) {
event.target.style.opacity = '';
}
}
};
</script>
<style scoped>
.drag-item {
position: absolute;
width: 100px;
height: 100px;
background-color: #ccc;
border-radius: 50%;
cursor: move;
display: flex;
align-items: center;
justify-content: center;
}
</style>
在這個例子中,我們使用了HTML5提供的拖放API來實現拖拽功能,具體來說:
- 將元素的draggable屬性設置為true,使它成為可拖拽元素
- 在元素上添加三個事件監聽器,分別處理拖拽開始、拖拽過程、拖拽結束三個事件
- 在onDragStart事件中,設置的drag data將會在onDrop事件中使用,這裡我們使用的是文本數據類型
- 在onDrag事件中,根據鼠標的坐標,實時更新的位置
- 在onDragEnd事件中,還原的透明度
三、使用Vue3 Composition API實現拖拽組件
在Vue3中,我們可以使用Composition API重構我們的代碼,使其更具可復用性和可維護性。下面是一個使用Composition API實現拖拽組件的示例:
<template>
<div
class="drag-item"
ref="dragItem"
v-draggable="{ dragData: 'Drag Me!', onDragStart, onDrag, onDragEnd }">
Drag Me!
</div>
</template>
<script>
import { ref } from 'vue';
import { useDraggable } from '@vueuse/core';
export default {
setup() {
const dragItem = ref(null);
useDraggable(dragItem);
const onDragStart = (event) => {
event.target.style.opacity = '0.4';
};
const onDrag = (event) => {
event.target.style.left = `${event.clientX}px`;
event.target.style.top = `${event.clientY}px`;
};
const onDragEnd = (event) => {
event.target.style.opacity = '';
};
return {
dragItem,
onDragStart,
onDrag,
onDragEnd,
};
},
};
</script>
<style scoped>
.drag-item {
position: absolute;
width: 100px;
height: 100px;
background-color: #ccc;
border-radius: 50%;
cursor: move;
display: flex;
align-items: center;
justify-content: center;
}
</style>
在這個示例中,我們使用Vue3的Composition API和vueuse庫來實現拖拽組件。具體來說:
- 使用useDraggable hook來封裝拖拽邏輯,並將拖拽組件的DOM元素傳遞給它
- 在v-draggable指令中,我們將拖拽數據、拖拽開始、拖拽過程、拖拽結束事件傳遞給了useDraggable hook
- 在onDragStart事件中,我們不需要設置drag data,因為這一步在useDraggable hook中已經處理了
- 在onDrag事件中,我們不需要手動設置元素的位置,因為useDraggable hook會自動更新位置
- 在onDragEnd事件中,我們只需要還原的透明度即可
四、使用拖拽組件實現可視化拖拽編輯器
我們可以使用拖拽組件來實現一個可視化拖拽編輯器,讓用戶能夠通過可視化的方式編輯頁面布局。下面是一個使用Vue3和Element Plus實現的可視化拖拽編輯器的示例:
<template>
<div class="drag-editor">
<div class="drag-container">
<draggable
v-model="list"
:animation="200"
@end="onEnd">
<div
v-for="(item, index) in list"
:key="item.id"
:class="item.type"
class="drag-item"
ref="dragItem">
{{ item.name }}
</div>
</draggable>
</div>
<el-dialog
title="添加組件"
:visible.sync="dialogVisible"
width="30%"
:before-close="beforeDialogClose">
<el-select
placeholder="請選擇組件"
v-model="component"
style="width: 100%;">
<el-option
v-for="item in componentList"
:key="item.id"
:label="item.name"
:value="item">
<template #default>
{{ item.name }}
</template>
</el-option>
</el-select>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="handleAddComponent">確 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { ref } from 'vue';
import { v4 as uuidv4 } from 'uuid';
import { ElDialog, ElSelect, ElOption, ElButton } from 'element-plus';
import 'element-plus/lib/theme-chalk/index.css';
import { useDraggable, useDialog } from '@vueuse/core';
export default {
components: { ElDialog, ElSelect, ElOption, ElButton },
setup() {
const list = ref([
{
id: uuidv4(),
type: 'header',
name: 'Header',
},
{
id: uuidv4(),
type: 'paragraph',
name: 'Paragraph',
},
{
id: uuidv4(),
type: 'image',
name: 'Image',
},
]);
const component = ref(null);
const dialogVisible = ref(false);
const componentList = [
{ id: 1, name: 'Header' },
{ id: 2, name: 'Paragraph' },
{ id: 3, name: 'Image' },
];
const { showDialog, hideDialog } = useDialog();
const handleAddComponent = () => {
if (component.value) {
list.value.push({
id: uuidv4(),
type: component.value.type,
name: component.value.name,
});
hideDialog();
}
};
const { onDragStart, onDrop } = useDraggable({
onDragStart: (event) => {
event.dataTransfer.effectAllowed = 'move';
const { target } = event;
target.classList.add('dragging');
},
});
const onEnd = (event) => {
event.item.classList.remove('dragging');
};
return {
list,
component,
dialogVisible,
componentList,
handleAddComponent,
onDragStart,
onDrop,
onEnd,
showDialog,
};
},
};
</script>
<style scoped>
.drag-editor {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
height: 100%;
}
.drag-container {
display: flex;
flex-wrap: wrap;
max-width: 1024px;
padding: 20px;
}
.drag-item {
background-color: #1890ff;
border-radius: 4px;
color: #fff;
cursor: move;
display: inline-block;
margin-right: 10px;
margin-bottom: 10px;
padding: 10px;
user-select: none;
}
.dragging {
opacity: 0.4;
}
.el-dialog__wrapper {
display: none !important;
}
</style>
在這個示例中,我們使用了Element Plus的對話框、選擇器等組件,並使用了vueuse庫中的useDialog和useDraggable hook。具體來說:
- 使用useDialog hook來封裝對話框邏輯,表現為對話框的顯示/隱藏、插槽分發等功能
- 在handleAddComponent函數中,將選擇的組件添加到list變量中,實現了向可視化編輯器中添加組件的功能
- 在v-draggable指令中,我們僅傳遞onDragStart事件,因為useDraggable hook已經處理了其它拖拽事件
- 在onEnd事件中,還原拖拽元素的透明度
五、結語
本文介紹了使用Vue3實現拖拽組件的基本用法和Composition API優化方法,並通過構建一個可視化拖拽編輯器的示例,展示了使用拖拽組件來改善用戶體驗的實際應用。通過學習Vue3拖拽組件的相關知識,我們可以快速構建交互式UI組件,並提高用戶的工作效率。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/257921.html