Vue3+vuedraggable實(shí)現(xiàn)動(dòng)態(tài)配置頁(yè)面
1、首先放上最終效果圖,整個(gè)頁(yè)面由三個(gè)區(qū)域組成:
- 組件列表存放可以配置的組件名稱。
- 放置列表為最終展現(xiàn)的視覺(jué)效果。
- 組件輸入則可以動(dòng)態(tài)配置內(nèi)容,最終的配置數(shù)據(jù)為此處的數(shù)據(jù)。

1、框架搭建
1.1、安裝指定版本的vuedraggable
首先安裝支持vue3版本的vuedraggable
注意:默認(rèn)安裝的vuedraggable版本為vue2.0版本,并不通用。
npm install vuedraggable@4.1.0 --save
vue3版本vuedraggable示例地址sortablejs.github.io/vue.draggable.next
vue3版本vuedraggable Git地址 github.com/SortableJS/vue.draggable.next
1.2、布局搭建
安裝完4.0版本的vuedraggable以后,就可以按下面的寫法來(lái)進(jìn)行一個(gè)簡(jiǎn)單的布局了。
<template>
<div>
<div class="section-container">
<h4>組件列表</h4>
<draggable
class="components-view"
item-key="index"
:list="sectionList"
:sort="false"
:forceFallback="true"
ghost-class="ghost"
dragClass="dragClass"
group="vehicle-station"
>
<template #item="{ element, index }">
<div class="section">{{ element.type }}</div>
</template>
</draggable>
</div>
<div class="components-container">
<h4>放置列表</h4>
<draggable
item-key="index"
:list="componentsList"
animation="300"
:scroll="true"
:forceFallback="false"
ghost-class="ghost"
dragClass="dragClass"
group="vehicle-station">
<template #item="{ element, index }">
<transition name="el-fade-in-linear">
<div>
<div v-if="element.type === 'input'" class="section">輸入框{{ element.data }}</div>
<div v-if="element.type === 'textarea'" class="section">文本域</div>
</div>
</transition>
</template>
</draggable>
</div>
<!-- 這里存放組件 -->
<div class="operate-container">
<h4>組件輸入</h4>
</div>
</div>
</template>
需要注意的是vue3版本不再需要v-for來(lái)渲染組件,直接使用template來(lái)渲染元素,并且需要指定唯一的item-key值。
1.2、使用到的參數(shù)介紹
| 屬性名稱 | 說(shuō)明 |
|---|---|
| group | name相同的可以互相拖拽 |
| list | 拖拽的數(shù)組 |
| item-key | 唯一key值,不能重復(fù) |
| sort | 控制列表是否可以排序 |
| forceFallback | 默認(rèn)false,忽略HTML5的拖拽行為,因?yàn)樵O(shè)置了拖拽樣式,需要開啟 |
| ghost-class | 目標(biāo)位置占位符的樣式 |
| dragClass | 拖拽對(duì)象移動(dòng)樣式 |
| animation | 拖拽動(dòng)畫時(shí)間 |
| pull | clone,拖拽的元素不會(huì)從列表消失,直接克隆這條數(shù)據(jù) |
| put | false,禁止元素拖入 |
函數(shù)部分目前只需要定義數(shù)據(jù)結(jié)構(gòu)
<script setup lang="ts">
import { ref } from 'vue';
import draggable from 'vuedraggable'
interface list {
type: string,
name: string,
data: any
}
const sectionList = ref<list[]>([
{
type: 'input',
data: '',
name: 'input'
},
{
data: '',
type: 'textarea',
name: 'textarea'
}
])
const componentsList = ref<list[]>([])
</script>
css定義一下分欄布局和拖動(dòng)、占位樣式
<style scoped>
.components-view,
.components-wrap {
height: 100%;
}
.dragClass {
border: 1px solid red;
border-radius: 8px;
}
.ghost {
background-color: red !important;
}
.operate-container,
.section-container,
.components-container {
float: left;
padding-top: 30px;
text-align: center;
width: 300px;
height: 800px;
}
.section-container {
background-color: blanchedalmond;
}
.components-container {
margin-left: 30px;
background-color: rgb(184, 205, 178);
}
.operate-container {
margin-left: 30px;
background-color: rgb(125, 176, 228);
}
.section {
text-align: center;
width: 150px;
height: 80px;
line-height: 80px;
margin-bottom: 30px;
background-color: cadetblue;
cursor: pointer;
}
</style>
至此頁(yè)面就可以正常拖拽了,僅拖拽頁(yè)面不需要用到函數(shù)操作,只需要根據(jù)配置項(xiàng)把頁(yè)面布局完成即可。

2、數(shù)據(jù)接入
目前只是完成了組件的添加,接下來(lái)要把組件接入。
思路是單獨(dú)定義組件數(shù)據(jù),當(dāng)輸入完成以后,根據(jù)當(dāng)前拖動(dòng)的放置列表下標(biāo)來(lái)存儲(chǔ)數(shù)據(jù)。
2.1、為兩列拖拽元素添加拖拽結(jié)束事件

2.2、設(shè)置組件數(shù)據(jù)
組件數(shù)據(jù)和放置列表的數(shù)據(jù)是聯(lián)動(dòng)的,在編輯完組件以后,數(shù)據(jù)會(huì)存儲(chǔ)到放置列表內(nèi)。 此時(shí)需要在拖動(dòng)結(jié)束時(shí)獲取當(dāng)前拖動(dòng)的放置列表下標(biāo),再把數(shù)據(jù)賦值給組件數(shù)據(jù)
<div class="operate-container">
<h4>組件輸入</h4>
<div>
<!-- TODO:輸入數(shù)據(jù)的時(shí)候要雙向綁定,賦值給editorData -->
<input v-if="editorData.type === 'input'" type="text" v-model="editorData.data" @change="setEditorData">
<textarea v-if="editorData.type === 'textarea'" rows="4" cols="30" v-model="editorData.data"
@change="setEditorData"></textarea>
</div>
</div>
const onEnd = (evt: any) => {
setCurrent(evt.newIndex)
}
-----
const setCurrent = (idx: number) => {
// 設(shè)置當(dāng)前編輯的組件數(shù)據(jù)
editorData.value = { ...componentsList.value[idx] }
editorIndex.value = idx
}
const setEditorData = () => {
// 將編輯的組件數(shù)據(jù)賦值給放置列表數(shù)據(jù)
componentsList.value[editorIndex.value] = editorData.value
}
最終實(shí)現(xiàn)效果如下,可以根據(jù)拖動(dòng)的組件展示不同的組件,并且可以輸入。

2.3、處理數(shù)據(jù)重復(fù)
上一步完成以后,組件數(shù)據(jù)已經(jīng)可以保留下來(lái)了,但是無(wú)法做到數(shù)據(jù)互不沖突,無(wú)論是新添加組件,還是編輯其中一個(gè)組件,數(shù)據(jù)都是相同的。
這是因?yàn)樵谕献У臅r(shí)候數(shù)據(jù)都是復(fù)制的,在修改完數(shù)據(jù)以后,最左側(cè)的組件列表會(huì)接收到最新修改的數(shù)據(jù),在下一次拖動(dòng)的時(shí)候就會(huì)把已經(jīng)修改的數(shù)據(jù)再次拿來(lái)使用。
目前想到的解決方案是獲取當(dāng)前拖動(dòng)的組件列表下標(biāo),和當(dāng)前放置列表的下標(biāo),手動(dòng)清除數(shù)據(jù)。
const onEnd = (evt: any) => {
if (evt.target.className === 'components-view' && evt.to.className === 'components-wrap') {
// 左側(cè)組件列表的下標(biāo)
sectionIndex.value = evt.oldIndex
}
setCurrent(evt.newIndex)
}
const setCurrent = (idx: number) => {
// 設(shè)置當(dāng)前編輯的組件數(shù)據(jù)
editorData.value = { ...componentsList.value[idx] }
editorIndex.value = idx
}
const setEditorData = () => {
// 填完值以后兩側(cè)數(shù)據(jù)都發(fā)生了改變,需要重新修改數(shù)據(jù)
// 把上一次拖動(dòng)的左側(cè)列表數(shù)據(jù)清空
sectionList.value[sectionIndex.value].data = ''
// 將編輯的組件數(shù)據(jù)賦值給放置列表數(shù)據(jù)
componentsList.value[editorIndex.value] = editorData.value
}
完成上述步驟以后,簡(jiǎn)單的動(dòng)態(tài)配置組件就已經(jīng)完成了,處理框架的代碼量并不大,后續(xù)可以在上面拓展新的組件,最終可以呈現(xiàn)出一個(gè)可以動(dòng)態(tài)配置的頁(yè)面。
以上就是Vue3+vuedraggable實(shí)現(xiàn)動(dòng)態(tài)配置頁(yè)面的詳細(xì)內(nèi)容,更多關(guān)于Vue3 vuedraggable動(dòng)態(tài)配置頁(yè)面的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue在echarts?tooltip中添加點(diǎn)擊事件案例詳解
本文主要介紹了Vue項(xiàng)目中在echarts?tooltip添加點(diǎn)擊事件的案例詳解,代碼具有一定的價(jià)值,感興趣的小伙伴可以來(lái)學(xué)習(xí)一下2021-11-11
vue與electron實(shí)現(xiàn)進(jìn)程間的通信詳情
這篇文章主要介紹了vue與electron實(shí)現(xiàn)進(jìn)程間的通信詳情,本文主要介紹electron渲染進(jìn)程和主進(jìn)程間的通信,以及在渲染進(jìn)程和主進(jìn)程中常用的配置項(xiàng),需要的朋友可以參考一下2022-09-09
Vue如何獲取url路由地址和參數(shù)簡(jiǎn)單示例
這篇文章主要給大家介紹了Vue如何獲取url路由地址和參數(shù)的相關(guān)資料,通過(guò)簡(jiǎn)單的代碼示例,幫助讀者快速掌握Vue路由的基本用法,需要的朋友可以參考下2023-03-03
Vue調(diào)用PC攝像頭實(shí)現(xiàn)拍照功能
這篇文章主要為大家詳細(xì)介紹了Vue調(diào)用PC攝像頭實(shí)現(xiàn)拍照功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
Vue列表循環(huán)從指定下標(biāo)開始的多種解決方案
這篇文章主要介紹了Vue列表循環(huán)從指定下標(biāo)開始的多種方案,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04

