<template><div class="resizable-container"><!-- 上半部分内容区 --><div class="resizable-top":style="{ height: topHeight + 'px' }">上半部分内容(可拖动下方分隔线调整高度)</div><!-- 拖动分隔线 --><div class="resizable-handle"@mousedown="startDrag":style="{ cursor: dragStatus ? 'row-resize' : 'row-resize' }"></div><!-- 下半部分内容区 --><div class="resizable-bottom":style="{ height: bottomHeight + 'px' }">下半部分内容</div></div></template><script>export default {name: "ResizableDiv",data() {return {// 容器总高度(可根据需求调整,也可动态获取父容器高度)containerHeight: 600,// 上半部分高度(初始值)topHeight: 300,// 下半部分高度(由总高度 - 上半部分高度 - 分隔线高度计算)bottomHeight: 298,// 拖动状态标记dragStatus: false,// 分隔线高度(固定)handleHeight: 4,// 上下部分最小高度限制minTopHeight: 100,minBottomHeight: 100startY:0,startTopHeight:0,};},mounted() {// 可选:动态获取父容器高度(替代固定 containerHeight)// this.containerHeight = this.$el.offsetHeight;// this.calcBottomHeight();// 监听全局鼠标移动和松开事件(避免拖动时鼠标移出分隔线失效)window.addEventListener("mousemove", this.onDrag);window.addEventListener("mouseup", this.endDrag);window.addEventListener("mouseleave", this.endDrag);},beforeDestroy() {// 移除全局事件监听(防止内存泄漏)window.removeEventListener("mousemove", this.onDrag);window.removeEventListener("mouseup", this.endDrag);window.removeEventListener("mouseleave", this.endDrag);},methods: {// 开始拖动:记录初始状态startDrag(e) {this.dragStatus = true;// 记录鼠标初始 Y 坐标(相对于容器顶部)this.startY = e.clientY - this.$el.getBoundingClientRect().top;// 记录拖动前的上半部分高度this.startTopHeight = this.topHeight;// 添加拖动时的全局样式(优化体验)document.body.style.userSelect = "none"; // 禁止文本选中document.body.style.cursor = "row-resize";},// 拖动中:计算高度变化onDrag(e) {if (!this.dragStatus) return;// 计算鼠标移动后的 Y 坐标(相对于容器顶部)const currentY = e.clientY - this.$el.getBoundingClientRect().top;// 计算上半部分高度变化值const diff = currentY - this.startY;let newTopHeight = this.startTopHeight + diff;// 边界控制:确保上半部分不小于最小高度,且下半部分也不小于最小高度const maxTopHeight = this.containerHeight - this.minBottomHeight - this.handleHeight;newTopHeight = Math.max(this.minTopHeight, Math.min(newTopHeight, maxTopHeight));// 更新上下部分高度this.topHeight = newTopHeight;this.calcBottomHeight();},// 结束拖动:重置状态endDrag() {this.dragStatus = false;// 恢复全局样式document.body.style.userSelect = "";document.body.style.cursor = "";},// 计算下半部分高度(总高度 - 上半部分高度 - 分隔线高度)calcBottomHeight() {this.bottomHeight = this.containerHeight - this.topHeight - this.handleHeight;}}};</script><style scoped>.resizable-container {width: 100%;height: 100%; /* 可根据父容器调整,或使用固定高度 */max-height: 800px;border: 1px solid #e8e8e8;border-radius: 4px;overflow: hidden;position: relative;}/* 上半部分内容区 */.resizable-top {width: 100%;overflow: auto; /* 内容超出时滚动 */background: #fafafa;padding: 16px;box-sizing: border-box;transition: height 0.1s ease; /* 平滑过渡 */}/* 拖动分隔线 */.resizable-handle {width: 100%;height: 4px;background: #ddd;cursor: row-resize;transition: background 0.2s;}/* 拖动时分隔线样式优化 */.resizable-handle:hover,.resizable-handle:active {background: #1890ff; /* Element UI 主题色,可自定义 */}/* 下半部分内容区 */.resizable-bottom {width: 100%;overflow: auto; /* 内容超出时滚动 */background: #fff;padding: 16px;box-sizing: border-box;transition: height 0.1s ease; /* 平滑过渡 */}</style>