使用vuedraggable和grid实现自定义拖拽布局
实现思路
使用vuedraggable实现拖拽功能,拖拽改变的是模块在list的顺序,使用gird设置动态类名,根据模块在list的位置匹配对应的gird样式。
效果图
每个模块可以拖拽,不同数量和不同位置模块宽度和高度不同(注意:模块样式width:100%,height:100%)

图1-标准布局

图2-三块布局

图3-自定义布局
<template>
<div class="wrap">
<div class="flex-row-start definelayout">
<div class="flex-row" @click="changelayout(layouttype.four)">
<div class="name">标准布局</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';
//资源对象
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]);
})
// 自定义当前页包含组件
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:
// 默认四宫格
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);
}
}
// 设置拖拽组件的样式
.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>
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论