vue3使用vuedraggable和grid實(shí)現(xiàn)自定義拖拽布局方式
使用vuedraggable和grid實(shí)現(xiàn)自定義拖拽布局
實(shí)現(xiàn)思路
使用vuedraggable實(shí)現(xiàn)拖拽功能,拖拽改變的是模塊在list的順序,使用gird設(shè)置動(dòng)態(tài)類名,根據(jù)模塊在list的位置匹配對(duì)應(yīng)的gird樣式。
效果圖
每個(gè)模塊可以拖拽,不同數(shù)量和不同位置模塊寬度和高度不同(注意:模塊樣式width:100%,height:100%)
圖1-標(biāo)準(zhǔn)布局
圖2-三塊布局
圖3-自定義布局
<template> <div class="wrap"> <div class="flex-row-start defineLayout"> <div class="flex-row" @click="changeLayout(LayoutType.FOUR)"> <div class="name">標(biāo)準(zhǔn)布局</div> </div> <div class="flex-row" @click="changeLayout(LayoutType.THREE)"> <div class="name">三塊布局</div> </div> <el-dropdown ref="dropdown1" trigger="contextmenu" style="margin-right: 30px"> <div class="flex-row el-dropdown-link" @click="() => { if (dropdown1) dropdown1.handleOpen(); }"> <div class="name">自定義布局</div> </div> <template #dropdown> <el-checkbox-group class="flex-col-start" v-model="checkedIdList" :max="4" style="padding: 10px 0 10px 30px;"> <el-checkbox @change="changeLayout(LayoutType.DEFINE)" v-for="(item, index) of cList" :key="index" :label='item.id'>{{ item.name }}</el-checkbox> </el-checkbox-group> </template> </el-dropdown> </div> <div class="draggable-border"> <draggable :list="moduleList" item-key="id" :options="{ animation: 200, ghostClass: 'ghost' }" :class="{ gird1col: moduleList.length == 1, gird2col: moduleList.length == 2, gird3col: moduleList.length == 3, gird4col: moduleList.length == 4 }"> <template #item="{ element, index }"> <component :ref="element.ref" :is="element.component" :name="element.name" :class="{ [`dragItem${index}`]: true, }"> </component> </template> </draggable> </div> </div> </template>
<script lang="ts" setup> import { ref, onMounted } from "vue"; import { useState, useMutations } from "@/utils/useStore"; import Block1 from '@/components/block1/block1'; import Block2 from '@/components/block2/block2'; import Block3 from '@/components/block3/block3'; import Block4 from '@/components/block4/block4'; import Block5 from '@/components/block5/block5.vue'; //@ts-ignore import draggable from "vuedraggable"; import { LayoutType } from '@/utils/enum'; //資源對(duì)象 let resource = ref<any>(); //@ts-ignore const { moduleList } = useState(["moduleList"], "drag"); //@ts-ignore const { setModuleList } = useMutations(["setModuleList"], "drag"); let dropdown1 = ref(); let checkedIdList = ref<number[]>([]);//自定義選擇的模塊 let cList: any[] = [ { type: '1', id: 1, name: '塊1', component: Block1 }, { type: '1', id: 2, name: '塊2', component: Block2 }, { type: '2', id: 3, name: '塊3', component: Block3 }, { type: '2', id: 4, name: '塊4', component: Block4 }, { type: '2', id: 5, name: '塊5', component: Block5 }, ]; onMounted(() => { setCompontent([1, 2, 3, 4]); }) // 自定義當(dāng)前頁包含組件 const setCompontent = (idList: number[]) => { checkedIdList.value = idList; let list = cList.filter((f: any) => { return idList.indexOf(f.id) != -1; }); setModuleList(list); console.log("list", list); }; // 切換布局 const changeLayout = (type) => { switch (type) { case LayoutType.THREE: setCompontent([1, 2, 5]); break; case LayoutType.DEFINE: if (checkedIdList.value) setCompontent(checkedIdList.value); break; default: // 默認(rèn)四宮格 setCompontent([1, 2, 3, 4]); break; } } </script>
<style scoped lang="scss"> .wrap { height: 100vh; width: 100vw; position: relative; display: block; overflow: hidden; .defineLayout { color: #fff; height: 41px; width: 100%; background-color: #000; align-items: center; padding: 0 20px; .name { font-size: 12px; font-weight: 500; color: #FFFFFF; line-height: 17px; margin-left: 5px; margin-right: 20px; cursor: pointer; } } .draggable-border { background-color: #fff; width: 100%; height: calc(100vh - 41px); } } // 設(shè)置拖拽組件的樣式 .draggable-border>div { width: 100%; height: 100%; display: grid; grid: 'one two' 'three four'; grid-template-columns: 50% 50%; grid-template-rows: 50% 50%; } .gird4col { grid: 'one two' 'three four' !important; grid-template-columns: 50% 50% !important; grid-template-rows: 50% 50% !important; } .gird3col { grid: 'one three' 'two three' !important; grid-template-columns: 50% 50% !important; grid-template-rows: 50% 50% !important; } .gird2col { grid: 'one two' 'one two' !important; grid-template-columns: 50% 50% !important; grid-template-rows: 50% 50% !important; } .gird1col { grid: 'one' !important; grid-template-columns: 100% !important; grid-template-rows: 100% !important; } .fullscreen { width: 100vw; height: 100vh; position: fixed; top: 0; left: 0; z-index: 999; } .dragItem0 { grid-area: one; } .dragItem1 { grid-area: two; } .dragItem2 { grid-area: three; } .dragItem3 { grid-area: four; } </style>
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue實(shí)現(xiàn)大文件分片上傳與斷點(diǎn)續(xù)傳到七牛云
這篇文章介紹了vue實(shí)現(xiàn)大文件分片上傳與斷點(diǎn)續(xù)傳到七牛云的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06Vue3+Element?Plus實(shí)現(xiàn)el-table跨行顯示(非腳手架)
這篇文章主要介紹了Vue3+Element Plus實(shí)現(xiàn)el-table跨行顯示(非腳手架),本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09Vue路由組件通過props配置傳參的實(shí)現(xiàn)
本文主要介紹了Vue路由組件通過props配置傳參的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06使用開源Cesium+Vue實(shí)現(xiàn)傾斜攝影三維展示功能
這篇文章主要介紹了使用開源Cesium+Vue實(shí)現(xiàn)傾斜攝影三維展示,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07解決VUE項(xiàng)目在IIS部署出現(xiàn):Uncaught SyntaxError: Unexpected&n
這篇文章介紹了解決VUE項(xiàng)目在IIS部署出現(xiàn):Uncaught SyntaxError: Unexpected token < 報(bào)錯(cuò)的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04vue router 跳轉(zhuǎn)時(shí)打開新頁面的示例方法
這篇文章主要介紹了vue router 跳轉(zhuǎn)時(shí)打開新頁面的示例方法,本文通過示例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-07-07基于vue3+threejs實(shí)現(xiàn)可視化大屏效果
本文主要主要講述對(duì)threejs的一些api進(jìn)行基本的封裝,在vue3項(xiàng)目中來實(shí)現(xiàn)一個(gè)可視化的3d項(xiàng)目,包含了一些常用的功能,場(chǎng)景、燈光、攝像機(jī)初始化,模型、天空盒的加載,以及鼠標(biāo)點(diǎn)擊和懸浮的事件交互,感興趣的朋友可以參考下2023-06-06vue的index.html中獲取環(huán)境變量和業(yè)務(wù)判斷圖文詳解
這篇文章主要給大家介紹了關(guān)于vue的index.html中獲取環(huán)境變量和業(yè)務(wù)判斷的相關(guān)資料,對(duì)vue來說index.html是一個(gè)總的入口文件,vue是單頁面應(yīng)用,掛在id為app的div下然后動(dòng)態(tài)渲染路由模板,需要的朋友可以參考下2023-09-09