最近遇到了一个需求,就是需要实现拖动中间划线拖拽来实现两侧宽度改变。
参考了博主的文章 - vuejs中拖动改变元素宽度实现宽度自适应大小 - 可可西里的骄傲 - 博客园 (cnblogs.com)
结果呢,转而去研究了offset类的知识 - 一文搞懂offset系列、client系列、scroll系列 - 掘金 (juejin.cn)
感觉适合于我特别不扎实的前端小白来讲,用www.runoob.com/ 来学习一些前端原理与知识是再好不过的啦!!!
感觉学习就是永不止境...追剧可以剧荒,但是学习永远都有下一场,不怕学慌!最近在追 夏目友人帐,一下子看了整整六季,听说今年有第七季。最近就是剧荒阶段,就用学习来弥补吧....
话说,弥补得了吗????
不管了,先学着看看 ...(口吐芬芳)若有错误,希望能帮我在评论区纠正一下哈,谢谢大家。
知识1 - ClientX
csharp
//clientX 事件属性返回当事件被触发时鼠标指针相对于浏览器页面(或客户区)的水平坐标。
//客户区指的是当前窗口。
event.clientX

知识2 - offset系列与client系列
offsetLeft - 元素边框外左边的水平距离(不包含边框)
offsetWidth - 元素宽度(包含边框)
clientWidth - 元素宽度(不包含边框)

知识3 - html dom事件对象之鼠标事件 - HTML DOM 事件对象 | 菜鸟教程 (runoob.com)
onmousedown - 鼠标按钮被按下事件
onmousemove - 鼠标被移动事件
onmouseup - 鼠标按键被松开事件
知识3 - html dom事件对象之鼠标事件
把 vuejs中拖动改变元素宽度实现宽度自适应大小 - 可可西里的骄傲 - 博客园 (cnblogs.com)博主写的主要代码(我认为)分析了一下。
-- 主要分析左边拖拽条哈。

ini
var resize = document.getElementsByClassName('resize');//左边拖拽条
var resize2 = document.getElementsByClassName('resize2');//右边拖拽条
var left = document.getElementsByClassName('left');//获得left div元素
var right = document.getElementsByClassName('right');//获得right div元素
var mid = document.getElementsByClassName('mid');//获得mid div元素
var box = document.getElementsByClassName('box');//获得box元素(left+resize+mid+right+resize2)
//1.当鼠标按下时:(1)先获取当前鼠标的水平x--startx
resize[0].onmousedown = function (e) {
var startX = e.clientX;
resize[0].left = resize[0].offsetLeft;
//2.当鼠标按下后移动时:(2)再获取拖拽之后鼠标的水平x--endx
document.onmousemove = function (e) {
var endX = e.clientX;
var rightW = right[0].offsetWidth;
(3)moveLen为最终left元素的宽度,其中(endX - startX)表示鼠标拖拽的长度,若为正数,则往右拖拽;若为负数,则往左拖拽。
var moveLen = resize[0].left + (endX - startX);
var maxT = box[0].clientWidth - resize[0].offsetWidth;
特别说明:movelen(left元素宽度)若小于150,表示拖拽向左过度,则让left元素==150,目的是为了不让left元素拖拽过度而消失;若大于原本left元素宽度+mid元素(最小设置为150)的话,表示向右拖拽过度,都覆盖掉第二个拖拽条resize2了,则需要讲拖拽条resize停在距离resize2拖拽条+150px的地方。
if (moveLen < 150) moveLen = 150;
if (moveLen > maxT - rightW - 150) moveLen = maxT - rightW - 150;
(4)设置左边元素长度为movelen,resize拖拽条位置为movelen,mid元素为整个box-right元素宽度-两个拖拽条宽度(10px)-movelen(当前left元素宽度)。
resize[0].style.left = moveLen;
left[0].style.width = moveLen + 'px';
mid[0].style.width = (box[0].clientWidth - moveLen - rightW - 10) + 'px';
}
//3.当鼠标松开时:
document.onmouseup = function (evt) {
document.onmousemove = null;
document.onmouseup = null;
resize[0].releaseCapture && resize[0].releaseCapture();//当鼠标进行松开操作时,触发 释放鼠标捕获。
}
resize[0].setCapture && resize[0].setCapture();//当鼠标进行按下操作,进行鼠标捕获。
return false; //用来阻止onmousedown进行向父级元素进行冒泡操作
}
右边也一样。
遇到的问题
作为前端小白的我,总会遇到一些奇葩的问题,比如:
(1)
ini
var resize = document.getElementsByClassName('resize');
document.getElementsByClassName('resize')
返回的是一个类数组对象,包含了所有具有指定类名('resize')的元素。
我遇到的问题就是resize.onmousedown
,一直鼠标猛点都点不动,排查了原因原来是这样子改: resize[0].onmousedown
,我完全忽略了一个网页中,叫resize的元素可以有很多个。
(2)
setCapture与releaseCapture这两兄弟已经被弃用了,建议改为:
scss
resize[0].releasePointerCapture && resize[0].releasePointerCapture(1);
resize[0].setPointerCapture && resize[0].setPointerCapture(1);
(3)
元素.clientx到底原理如何?
就是在整个你看得到的整个屏幕上,与左屏幕边缘到鼠标的距离。 所以,若box嵌套在屏幕中规定的某个子div中,记得要剪掉左div(其他元素)的宽度。 总得一句话,要保证与box左边缘的距离,而不是与屏幕左边缘的距离,后者可能会导致后期移动有误吧。
我的代码
源代码-vue中实现拖动调整左右两侧div的宽度 - 掘金 (juejin.cn)
我修改了一丢丢而已。

xml
<template>
<div>
<el-row type="flex" class="row-bg" justify="space-between">
<el-col :span="3" class="col01">
a
</el-col>
<el-col :span="20">
<div class="box" ref="box">
<div class="left">
<!--左侧div内容-->11111
</div>
<div class="resize" title="收缩侧边栏">
⋮
</div>
<div class="mid">
<!--右侧div内容-->33333
</div>
</div>
</el-col>
<el-col :span="1">
c
</el-col>
</el-row>
</div>
</template>
<script>
export default {
data() {
return {}
},
mounted() {
this.dragControllerDiv();
},
methods: {
dragControllerDiv: function() {
var resize = document.getElementsByClassName('resize');
var left = document.getElementsByClassName('left');
var mid = document.getElementsByClassName('mid');
var box = document.getElementsByClassName('box');
var col01=document.getElementsByClassName('col01');
// 鼠标按下事件
resize[0].onmousedown = function(e) {
//颜色改变提醒
resize[0].style.background = '#818181';
var startX = e.clientX-col01[0].offsetWidth;
resize[0].left = resize[0].offsetLeft;
// 鼠标拖动事件
document.onmousemove = function(e) {
var endX = e.clientX-col01[0].offsetWidth;
var moveLen = resize[0].left + (endX -startX)-col01[0].offsetWidth;
var maxT = box[0].clientWidth - resize[0].offsetWidth;
if (moveLen < 32) moveLen = 32;
if (moveLen > maxT - 150) moveLen = maxT - 150;
resize[0].style.left = moveLen;
left[0].style.width = moveLen + 'px';
mid[0].style.width = (box[0].clientWidth - moveLen - 10) + 'px';
};
// 鼠标松开事件
document.onmouseup = function(evt) {
//颜色恢复
resize[0].style.background = '#d6d6d6';
document.onmousemove = null;
document.onmouseup = null;
resize[0].releasePointerCapture && resize[0].releasePointerCapture(1);
};
resize[0].setPointerCapture && resize[0].setPointerCapture(1);
return false;
};
},
}
}
</script>
<style scoped>
.el-col {
margin: 3px;
}
/* 拖拽相关样式 */
/*包围div样式*/
.box {
width: 100%;
height: 100%;
overflow: hidden;
}
.mid {
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;
}
.left {
float: left;
width: 68%;
/*右侧初始化宽度*/
height: 100%;
background: #fff;
}
</style>