vue3 基于element-plus进行的一个可拖动改变导航与内容区域大小的简单方法
1、先上个截图:
说明:拖动上面的分隔栏就可以实现,改变左右区域的大小。
2、上面的例子来自官网的:
Container 布局容器 | Element Plus
3、拖动的效果来自:
https://juejin.cn/post/7029640316999172104#heading-1
4、我们将二个效果,进行了组合,代码:
<template>
<el-container class="box" style="height: 100vh">
<el-aside width="200px" class="left">
<el-scrollbar>
<el-menu :default-openeds="['1', '3']">
<el-sub-menu index="1">
<template #title>
<el-icon><message /></el-icon>Navigator One
</template>
<el-menu-item-group>
<template #title>Group 1</template>
<el-menu-item index="1-1">Option 1</el-menu-item>
<el-menu-item index="1-2">Option 2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="Group 2">
<el-menu-item index="1-3">Option 3</el-menu-item>
</el-menu-item-group>
<el-sub-menu index="1-4">
<template #title>Option4</template>
<el-menu-item index="1-4-1">Option 4-1</el-menu-item>
</el-sub-menu>
</el-sub-menu>
<el-sub-menu index="2">
<template #title>
<el-icon><icon-menu /></el-icon>Navigator Two
</template>
<el-menu-item-group>
<template #title>Group 1</template>
<el-menu-item index="2-1">Option 1</el-menu-item>
<el-menu-item index="2-2">Option 2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="Group 2">
<el-menu-item index="2-3">Option 3</el-menu-item>
</el-menu-item-group>
<el-sub-menu index="2-4">
<template #title>Option 4</template>
<el-menu-item index="2-4-1">Option 4-1</el-menu-item>
</el-sub-menu>
</el-sub-menu>
<el-sub-menu index="3">
<template #title>
<el-icon><setting /></el-icon>Navigator Three
</template>
<el-menu-item-group>
<template #title>Group 1</template>
<el-menu-item index="3-1">Option 1</el-menu-item>
<el-menu-item index="3-2">Option 2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="Group 2">
<el-menu-item index="3-3">Option 3</el-menu-item>
</el-menu-item-group>
<el-sub-menu index="3-4">
<template #title>Option 4</template>
<el-menu-item index="3-4-1">Option 4-1</el-menu-item>
</el-sub-menu>
</el-sub-menu>
</el-menu>
</el-scrollbar>
</el-aside>
<div class="resize"></div>
<el-container class="mid">
<el-header style="text-align: right; font-size: 12px">
<div class="toolbar">
<el-dropdown>
<el-icon style="margin-right: 8px; margin-top: 1px">
<setting />
</el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>View</el-dropdown-item>
<el-dropdown-item>Add</el-dropdown-item>
<el-dropdown-item>Delete</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<span>Tom</span>
</div>
</el-header>
<el-main>
<el-scrollbar>
<el-table :data="tableData">
<el-table-column prop="date" label="Date" width="140" />
<el-table-column prop="name" label="Name" width="120" />
<el-table-column prop="address" label="Address" />
</el-table>
</el-scrollbar>
</el-main>
</el-container>
</el-container>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from "vue";
import { Menu as IconMenu, Message, Setting } from "@element-plus/icons-vue";
const item = {
date: "2016-05-02",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
};
const tableData = ref(Array.from({ length: 20 }).fill(item));
function dragControllerDiv() {
var resize = document.getElementsByClassName("resize");
var left = document.getElementsByClassName("left");
var mid = document.getElementsByClassName("mid");
var box = document.getElementsByClassName("box");
for (let i = 0; i < resize.length; i++) {
// 鼠标按下事件
resize[i].onmousedown = function (e) {
//颜色改变提醒
resize[i].style.background = "#818181";
var startX = e.clientX;
resize[i].left = resize[i].offsetLeft;
// 鼠标拖动事件
document.onmousemove = function (e) {
var endX = e.clientX;
var moveLen = resize[i].left + (endX - startX); // (endx-startx)=移动的距离。resize[i].left+移动的距离=左边区域最后的宽度
var maxT = box[i].clientWidth - resize[i].offsetWidth; // 容器宽度 - 左边区域的宽度 = 右边区域的宽度
if (moveLen < 32) moveLen = 32; // 左边区域的最小宽度为32px
if (moveLen > maxT - 150) moveLen = maxT - 150; //右边区域最小宽度为150px
resize[i].style.left = moveLen; // 设置左侧区域的宽度
for (let j = 0; j < left.length; j++) {
left[j].style.width = moveLen + "px";
mid[j].style.width = box[i].clientWidth - moveLen - 10 + "px";
}
};
// 鼠标松开事件
document.onmouseup = function (evt) {
//颜色恢复
resize[i].style.background = "#d6d6d6";
document.onmousemove = null;
document.onmouseup = null;
resize[i].releaseCapture && resize[i].releaseCapture(); //当你不在需要继续获得鼠标消息就要应该调用ReleaseCapture()释放掉
};
resize[i].setCapture && resize[i].setCapture(); //该函数在属于当前线程的指定窗口里设置鼠标捕获
return false;
};
}
}
onMounted(() => {
dragControllerDiv();
});
</script>
<style scoped>
.layout-container-demo .el-header {
position: relative;
background-color: var(--el-color-primary-light-7);
color: var(--el-text-color-primary);
}
.layout-container-demo .el-aside {
color: var(--el-text-color-primary);
background: var(--el-color-primary-light-8);
}
.layout-container-demo .el-menu {
border-right: none;
}
.layout-container-demo .el-main {
padding: 0;
}
.layout-container-demo .toolbar {
display: inline-flex;
align-items: center;
justify-content: center;
height: 100%;
right: 20px;
}
/* 拖拽相关样式 */
/*包围div样式*/
.box {
width: 100%;
height: 100%;
margin: 1% 0px;
overflow: hidden;
box-shadow: -1px 9px 10px 3px rgba(0, 0, 0, 0.11);
}
/*左侧div样式*/
.left {
width: calc(32% - 10px); /*左侧初始化宽度*/
height: 100%;
background: #ffffff;
float: left;
}
/*拖拽区div样式*/
.resize {
cursor: col-resize;
float: left;
position: relative;
top: 45%;
background-color: #d6d6d6;
border-radius: 5px;
margin-top: -10px;
width: 10px;
height: 50px;
background-size: cover;
background-position: center;
/*z-index: 99999;*/
font-size: 32px;
color: white;
}
/*拖拽区鼠标悬停样式*/
.resize:hover {
color: #444444;
}
/*右侧div'样式*/
.mid {
float: left;
width: 68%; /*右侧初始化宽度*/
height: 100%;
background: #fff;
box-shadow: -1px 4px 5px 3px rgba(0, 0, 0, 0.11);
}
</style>
5、通过上面的代码,我们可以很轻松的实现拖动改变左右二侧区域的大小,说明:
document.getElementsByClassName:返回一个类似数组的对象,包含了所有指定 class 名称的子元素。比如document.getElementsByClassName("left"); 是查找class="left"的所有的elements。
document.onmousemove = function (e) {
var endX = e.clientX;
var moveLen = resize[i].left + (endX - startX); // (endx-startx)=移动的距离。resize[i].left+移动的距离=左边区域最后的宽度
var maxT = box[i].clientWidth - resize[i].offsetWidth; // 容器宽度 - 左边区域的宽度 = 右边区域的宽度if (moveLen < 32) moveLen = 32; // 左边区域的最小宽度为32px
if (moveLen > maxT - 150) moveLen = maxT - 150; //右边区域最小宽度为150pxresize[i].style.left = moveLen; // 设置左侧区域的宽度
for (let j = 0; j < left.length; j++) {
left[j].style.width = moveLen + "px";
mid[j].style.width = box[i].clientWidth - moveLen - 10 + "px";
}
};
这里的left[j],mid[j], length=1的时候,就是第一个元素,也就是我们左侧导航与右侧数据。
容器宽度 = 左边区域的宽度 + resize的宽度 + 右边区域的宽度
resize[0]的left就是左侧的宽度。