前言: 有一个需求,需要在页面中显示两个表格,横向或纵向排列,在页面中希望像窗口样通过拖动来显示想要查看区域的大小。这里使用vue来实现。
实现地址:vitejsvitebyrurc-f311--5173.local-corp.webcontainer.io
实现思路
- 页面由左右或上下容器和分割线组成。
- 页面初始化的时候,获取可显示区域的宽高。横向排列的时候,表格的宽度为可视区域的一半并且减去分割线宽度的一半,表格的高度由内容来撑满;纵向排列的时候表格的高度为可视区域的一半并且减去分割线高度的一半,宽度则为100%;
- 通过监听鼠标的位置来动态修改表格宽度。
具体过程
- 布局和参数
页面由三部分组成,通过插槽来获取左右或上下内容,通过中间的分割线拖动修改宽度。为了支持横向排列和纵向排列,还需要一个参数direction,默认为横向排列row,纵向为col。具体实现如下:
<div>
<div>
<slot name="upOrLeft"></slot>
</div>
<div></div>
<div>
<slot name="downOrRight"></slot>
</div>
</div>
type Props = {
direction?: string;
};
const { direction } = withDefaults(defineProps<Props>(), {
direction: 'row',
});
- 逻辑实现
鼠标在分割线中按下为开始,监听鼠标的移动,通过获取鼠标的clientX或clientY来计算表格的宽度或高度。鼠标抬起,移除监听。具体实现如下:
<div :class="`dividing-${direction}`">
<div class="upOrLeft" :style="areaInfo.upOrLeft">
<slot name="upOrLeft"></slot>
</div>
<div
ref="dividingLineRef"
:class="`dividingLine-${direction}`"
@mousedown="mouseDown"
@mouseup="mouseUp"
></div>
<div class="downOrRight" :style="areaInfo.downOrRight">
<slot name="downOrRight"></slot>
</div>
</div>
const mouseUp = () => {
window.removeEventListener('mousemove', mouseMove);
};
const computedWidthHeight = (val: number) => {
return val - dividingLineWidth / 2;
};
const mouseMove = (e: MouseEvent) => {
if (direction === 'row') {
areaInfo.upOrLeft.width = computedWidthHeight(e.clientX) + 'px';
areaInfo.downOrRight.width =
computedWidthHeight(width.value - e.clientX) + 'px';
} else if (direction === 'col') {
areaInfo.upOrLeft.height = computedWidthHeight(e.clientY) + 'px';
areaInfo.downOrRight.height =
computedWidthHeight(height.value - e.clientY) + 'px';
}
};
const mouseDown = () => {
window.addEventListener('mousemove', mouseMove);
};
const initWidthHeight = (val: number) => {
return (val - dividingLineWidth) / 2;
};
const initPosition = () => {
if (direction === 'row') {
areaInfo.upOrLeft.width = initWidthHeight(width.value) + 'px';
areaInfo.downOrRight.width = initWidthHeight(width.value) + 'px';
} else if (direction === 'col') {
areaInfo.upOrLeft.height = initWidthHeight(height.value) + 'px';
areaInfo.downOrRight.height = initWidthHeight(height.value) + 'px';
}
};
const init = () => {
initPosition();
};
init();
这样动态修改表格宽度的组件就做好了。
结语:这里的可是区域是以浏览器为准的,在实际使用中,会放到大小各异的区域中,可以把放置区域的宽高通过参数传给组件来实现更高的兼容性。完整代码可以参考上面的链接。