vue拖动改变两侧宽度

最近遇到了一个需求,就是需要实现拖动中间划线拖拽来实现两侧宽度改变。

参考了博主的文章 – vuejs中拖动改变元素宽度实现宽度自适应大小 – 可可西里的骄傲 – 博客园 (cnblogs.com)

结果呢,转而去研究了offset类的知识 – 一文搞懂offset系列、client系列、scroll系列 – 掘金 (juejin.cn)

感觉适合于我特别不扎实的前端小白来讲,用www.runoob.com/ 来学习一些前端原理与知识是再好不过的啦!!!

感觉学习就是永不止境…追剧可以剧荒,但是学习永远都有下一场,不怕学慌!最近在追 夏目友人帐,一下子看了整整六季,听说今年有第七季。最近就是剧荒阶段,就用学习来弥补吧….

话说,弥补得了吗????

不管了,先学着看看 …(口吐芬芳)若有错误,希望能帮我在评论区纠正一下哈,谢谢大家。

知识1 – ClientX

//clientX 事件属性返回当事件被触发时鼠标指针相对于浏览器页面(或客户区)的水平坐标。
//客户区指的是当前窗口。
event.clientX

vue拖动改变两侧宽度

知识2 – offset系列与client系列

offsetLeft - 元素边框外左边的水平距离(不包含边框)
offsetWidth - 元素宽度(包含边框)
clientWidth - 元素宽度(不包含边框)

vue拖动改变两侧宽度

知识3 – html dom事件对象之鼠标事件HTML DOM 事件对象 | 菜鸟教程 (runoob.com)

onmousedown - 鼠标按钮被按下事件
onmousemove - 鼠标被移动事件
onmouseup - 鼠标按键被松开事件

知识3 – html dom事件对象之鼠标事件

vuejs中拖动改变元素宽度实现宽度自适应大小 – 可可西里的骄傲 – 博客园 (cnblogs.com)博主写的主要代码(我认为)分析了一下。

— 主要分析左边拖拽条哈。

vue拖动改变两侧宽度

      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)

var resize = document.getElementsByClassName('resize');

document.getElementsByClassName('resize')返回的是一个类数组对象,包含了所有具有指定类名(’resize’)的元素。

我遇到的问题就是resize.onmousedown,一直鼠标猛点都点不动,排查了原因原来是这样子改:
resize[0].onmousedown,我完全忽略了一个网页中,叫resize的元素可以有很多个。

(2)

setCapture与releaseCapture这两兄弟已经被弃用了,建议改为:

resize[0].releasePointerCapture && resize[0].releasePointerCapture(1); 
resize[0].setPointerCapture && resize[0].setPointerCapture(1); 

(3)

元素.clientx到底原理如何?

就是在整个你看得到的整个屏幕上,与左屏幕边缘到鼠标的距离。
所以,若box嵌套在屏幕中规定的某个子div中,记得要剪掉左div(其他元素)的宽度。
总得一句话,要保证与box左边缘的距离,而不是与屏幕左边缘的距离,后者可能会导致后期移动有误吧。

我的代码

源代码-vue中实现拖动调整左右两侧div的宽度 – 掘金 (juejin.cn)

我修改了一丢丢而已。

vue拖动改变两侧宽度

<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>

原文链接:https://juejin.cn/post/7345352532657586227 作者:爱追剧的小mo

(0)
上一篇 2024年3月13日 上午10:10
下一篇 2024年3月13日 上午10:21

相关推荐

发表回复

登录后才能评论