Vue3+vuedraggable實現(xiàn)動態(tài)配置頁面
1、首先放上最終效果圖,整個頁面由三個區(qū)域組成:
- 組件列表存放可以配置的組件名稱。
- 放置列表為最終展現(xiàn)的視覺效果。
- 組件輸入則可以動態(tài)配置內(nèi)容,最終的配置數(shù)據(jù)為此處的數(shù)據(jù)。
1、框架搭建
1.1、安裝指定版本的vuedraggable
首先安裝支持vue3版本的vuedraggable
注意:默認安裝的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以后,就可以按下面的寫法來進行一個簡單的布局了。
<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來渲染組件,直接使用template來渲染元素,并且需要指定唯一的item-key值。
1.2、使用到的參數(shù)介紹
屬性名稱 | 說明 |
---|---|
group | name相同的可以互相拖拽 |
list | 拖拽的數(shù)組 |
item-key | 唯一key值,不能重復 |
sort | 控制列表是否可以排序 |
forceFallback | 默認false,忽略HTML5的拖拽行為,因為設置了拖拽樣式,需要開啟 |
ghost-class | 目標位置占位符的樣式 |
dragClass | 拖拽對象移動樣式 |
animation | 拖拽動畫時間 |
pull | clone,拖拽的元素不會從列表消失,直接克隆這條數(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定義一下分欄布局和拖動、占位樣式
<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>
至此頁面就可以正常拖拽了,僅拖拽頁面不需要用到函數(shù)操作,只需要根據(jù)配置項把頁面布局完成即可。
2、數(shù)據(jù)接入
目前只是完成了組件的添加,接下來要把組件接入。
思路是單獨定義組件數(shù)據(jù),當輸入完成以后,根據(jù)當前拖動的放置列表下標來存儲數(shù)據(jù)。
2.1、為兩列拖拽元素添加拖拽結(jié)束事件
2.2、設置組件數(shù)據(jù)
組件數(shù)據(jù)和放置列表的數(shù)據(jù)是聯(lián)動的,在編輯完組件以后,數(shù)據(jù)會存儲到放置列表內(nèi)。 此時需要在拖動結(jié)束時獲取當前拖動的放置列表下標,再把數(shù)據(jù)賦值給組件數(shù)據(jù)
<div class="operate-container"> <h4>組件輸入</h4> <div> <!-- TODO:輸入數(shù)據(jù)的時候要雙向綁定,賦值給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ù)據(jù) editorData.value = { ...componentsList.value[idx] } editorIndex.value = idx } const setEditorData = () => { // 將編輯的組件數(shù)據(jù)賦值給放置列表數(shù)據(jù) componentsList.value[editorIndex.value] = editorData.value }
最終實現(xiàn)效果如下,可以根據(jù)拖動的組件展示不同的組件,并且可以輸入。
2.3、處理數(shù)據(jù)重復
上一步完成以后,組件數(shù)據(jù)已經(jīng)可以保留下來了,但是無法做到數(shù)據(jù)互不沖突,無論是新添加組件,還是編輯其中一個組件,數(shù)據(jù)都是相同的。
這是因為在拖拽的時候數(shù)據(jù)都是復制的,在修改完數(shù)據(jù)以后,最左側(cè)的組件列表會接收到最新修改的數(shù)據(jù),在下一次拖動的時候就會把已經(jīng)修改的數(shù)據(jù)再次拿來使用。
目前想到的解決方案是獲取當前拖動的組件列表下標,和當前放置列表的下標,手動清除數(shù)據(jù)。
const onEnd = (evt: any) => { if (evt.target.className === 'components-view' && evt.to.className === 'components-wrap') { // 左側(cè)組件列表的下標 sectionIndex.value = evt.oldIndex } setCurrent(evt.newIndex) } const setCurrent = (idx: number) => { // 設置當前編輯的組件數(shù)據(jù) editorData.value = { ...componentsList.value[idx] } editorIndex.value = idx } const setEditorData = () => { // 填完值以后兩側(cè)數(shù)據(jù)都發(fā)生了改變,需要重新修改數(shù)據(jù) // 把上一次拖動的左側(cè)列表數(shù)據(jù)清空 sectionList.value[sectionIndex.value].data = '' // 將編輯的組件數(shù)據(jù)賦值給放置列表數(shù)據(jù) componentsList.value[editorIndex.value] = editorData.value }
完成上述步驟以后,簡單的動態(tài)配置組件就已經(jīng)完成了,處理框架的代碼量并不大,后續(xù)可以在上面拓展新的組件,最終可以呈現(xiàn)出一個可以動態(tài)配置的頁面。
以上就是Vue3+vuedraggable實現(xiàn)動態(tài)配置頁面的詳細內(nèi)容,更多關于Vue3 vuedraggable動態(tài)配置頁面的資料請關注腳本之家其它相關文章!
相關文章
Vue在echarts?tooltip中添加點擊事件案例詳解
本文主要介紹了Vue項目中在echarts?tooltip添加點擊事件的案例詳解,代碼具有一定的價值,感興趣的小伙伴可以來學習一下2021-11-11