1,左右布局
2,上中下布局
3,分辨率自适应
vue2 版本代码
<template>
<div class="app-container">
<div class="left" :style="{ width: leftWidth + 'px' }">
<div class="right-center-left">
左边的内容,可以很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
</div>
</div>
<div class="divider" @mousedown="startDragging"></div>
<div class="right">
<div v-if="showDiv1" class="div1">查询条件</div>
<div class="div2">
<button @click="toggleDiv1">操作按钮 div1</button>
</div>
<div class="div3" :style="{ height: div3Height + 'px' }">
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
</div>
<div class="div4">分页</div>
</div>
</div>
</template>
<script>
export default {
name: "AppContainer",
data() {
return {
isDragging: false,
leftWidth: 200,
showDiv1: true
};
},
computed: {
div3Height() {
const totalHeight = window.innerHeight;
const div2Height = 30;
const div4Height = 30;
const div1Height = this.showDiv1 ? 100 : 0;
// 计算 div3 的高度
return totalHeight - div2Height - div4Height - div1Height;
}
},
methods: {
startDragging(e) {
this.isDragging = true;
document.addEventListener("mousemove", this.onDrag);
document.addEventListener("mouseup", this.stopDragging);
},
onDrag(e) {
if (this.isDragging) {
const minWidth = 50;
const maxWidth = window.innerWidth - 50;
const newLeftWidth = e.clientX;
if (newLeftWidth > minWidth && newLeftWidth < maxWidth) {
this.leftWidth = newLeftWidth;
}
}
},
stopDragging() {
this.isDragging = false;
document.removeEventListener("mousemove", this.onDrag);
document.removeEventListener("mouseup", this.stopDragging);
},
toggleDiv1() {
this.showDiv1 = !this.showDiv1;
}
}
};
</script>
<style scoped>
.app-container {
display: flex;
height: 100vh;
overflow: hidden;
}
.left {
overflow-x: auto;
overflow-y: auto;
white-space: nowrap;
min-width: 90px;
}
.divider {
width: 5px;
cursor: ew-resize;
background-color: #ccc;
}
.right {
display: flex;
flex-direction: column;
height: 100%;
flex: 1; /* 自动填满剩余宽度 */
}
.div1 {
height: 100px;
background-color: #f0f0f0;
}
.div2 {
height: 30px;
background-color: #ddd;
}
.div3 {
overflow-x: auto; /* 添加横向滚动条 */
overflow-y: auto; /* 添加纵向滚动条 */
background-color: #f5f5f5;
}
.div4 {
height: 200px;
background-color: #ccc;
}
</style>
vue3 版本代码
<template>
<div class="app-container">
<div class="left" :style="{ width: leftWidth + 'px' }">
左边的内容,可以很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
</div>
<div class="divider" @mousedown="startDragging"></div>
<div class="right">
<div v-if="showQueryDiv" class="right-query">搜索条件</div>
<div class="right-button">
<div class="right-button-left">操作按钮</div>
<div class="right-button-right">
<button @click="toggleQueryDiv">隐藏/展示 搜索条件</button>
</div>
</div>
<div class="right-table" :style="{ height: tableHeight + 'px' }">
表格内容<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />1<br />
</div>
<div class="right-page">分页内容</div>
</div>
</div>
</template>
<script>
import { ref, computed, onMounted, onUnmounted } from 'vue';
export default {
name: "AppContainer",
setup() {
const isDragging = ref(false);
const leftWidth = ref(200);
const showQueryDiv = ref(true);
const tableHeight = computed(() => {
const totalHeight = window.innerHeight;
const buttonHeight = 30;
const pageHeight = 30;
const queryHeight = showQueryDiv.value ? 100 : 0;
return totalHeight - buttonHeight - pageHeight - queryHeight;
});
const startDragging = (e) => {
isDragging.value = true;
document.addEventListener("mousemove", onDrag);
document.addEventListener("mouseup", stopDragging);
};
const onDrag = (e) => {
if (isDragging.value) {
const minWidth = 50;
const maxWidth = window.innerWidth - 50;
const newLeftWidth = e.clientX;
if (newLeftWidth > minWidth && newLeftWidth < maxWidth) {
leftWidth.value = newLeftWidth;
}
}
};
const stopDragging = () => {
isDragging.value = false;
document.removeEventListener("mousemove", onDrag);
document.removeEventListener("mouseup", stopDragging);
};
const toggleQueryDiv = () => {
showQueryDiv.value = !showQueryDiv.value;
};
onMounted(() => {
window.addEventListener("resize", onDrag);
});
onUnmounted(() => {
window.removeEventListener("resize", onDrag);
});
return {
leftWidth,
showQueryDiv,
tableHeight,
startDragging,
toggleQueryDiv
};
}
};
</script>
<style scoped>
.app-container {
display: flex;
height: 100vh;
overflow: hidden;
}
.left {
overflow-x: auto;
overflow-y: auto;
white-space: nowrap;
min-width: 90px;
}
.divider {
width: 5px;
cursor: ew-resize;
background-color: #ccc;
}
.right {
display: flex;
flex-direction: column;
height: 100%;
flex: 1; /* 自动填满剩余宽度 */
}
.right-query {
height: 100px;
background-color: #f0f0f0;
}
.right-button {
height: 30px;
display: flex;
justify-content: space-between; /* 左右对齐内容 */
align-items: center; /* 垂直居中对齐 */
background-color: #ddd;
}
.right-button-left {
margin-left: 5px;
text-align: left;
}
.right-button-right {
margin-right: 5px;
text-align: right;
}
.right-table {
overflow-x: auto; /* 添加横向滚动条 */
overflow-y: auto; /* 添加纵向滚动条 */
background-color: #f5f5f5;
}
.right-page {
height: 200px;
background-color: #ccc;
}
</style>
这个功能,从毕业就开始思索,直到八年后的今天成熟完善,真是艰辛也是很不容易。目前市面上没有见过有人实现,很多人都是只言片语的,基本复制下来,无法达到效果。我这个一键复制到自己的项目,就能实现了,中间的坎坷不平,到了完全实现的这一刻,才觉得激动不已。
无任何坑,也没有任何额外的引入,一个普普通通,最简单的vue页面,布局建好,里面的内容就可以自己随意发挥了。
未觉池塘春草梦,阶前梧叶已秋声。记录激动时刻,也造福后来人。