<1>.已实现功能
1.PC端Vue项目(或html)实现鼠标左右拖拽盒子滑动
2.同一盒子上鼠标移入移出事件和单击事件click冲突问题
3.子盒子移动,如何让边界不超出父盒子边界?
注意: 本文主要涉及到PC端鼠标横向拖拽问题的解决,移动端的解决方案很多,请详见其他文章,不在这里赘述.
<2>.代码及原理
需求描述:横向有一个菜单栏, 菜单tab过多,让他实现左右可以拖拽滑动
我们设置一个大盒子grand, 然后是父盒子parent和子盒子child. 其中grand你可以在pc端设置百分比宽度,而子盒子使用px或者em或者rem宽度,让他撑开父盒子.
这是html代码
<div class="grand">
<div class="parent">
<div class="child"
v-for=(item,indx) in menuList
:key="index"
@mousedown="handlemouse"
@mouseleve="leave"
@click="clickDoSome(index)"
>
{{item.name}}
</div>
</div>
</div>
这是css代码
.grand{
height: 60px;
position: relative;
overflow: hidden; 超出隐藏
}
.parent{
position: absolute;
white-space: nowrap; 设置不换行
}
grand盒子要relative定位, parent就是绝对定位且不能换行. 原理就是我们在鼠标移入目标盒子,左键点击,开始记录鼠标移动的位置,根据鼠标移动的px来设置parent的位置,鼠标左键抬起,停止拖拽.同时,click也会涉及左键点击和抬起的过程,所以这里会有冲突
html和css代码如此简练,所以js肯定会多一点
设置两个变量,分别控制和判断是否在拖拽还是单击
data(){
return {
isDrag:false,//是否在拖拽
isClick:false,//是否是单击
}
}
/**
* @brief 监听鼠标移入横向菜单栏
**/
handlemouse(e){
let startTime,endTime;
let child=document.getElementsByClassName('parent')[0];
let parent=document.getElementsByClassName('grand')[0];
// 使用this.$refs.name获取dom元素,可能会获取到vue组件,他不支持获取元素的宽高以及监听鼠标事件
let widthDiffer=parent.offsetWidth - child.offsetWidth;
if(widthDiffer>0){
//如果grand真实宽度比parent宽度长,那么就不用滑动了,直接返回
this.isClick=true;
return
}
startTime=new Date().getTime();//获取事件开始时间
let disx= e.clientX - child.offsetLeft;
this.isDrag=true;//设置开始拖拽
parent.onmousemove =(e)=>{
if(this.isDrag){//拖拽中
let mouseX=e.clientX; // 鼠标点击的位置
let x=mouseX-disx;
child.style.left=x+'px'//设置parent的位置
}
}
parent.onmouseup=(e)=>{
endTime=new Date().getTime();
let timeDiffer=endTime-startTime;//获取抬起时间
this.isDrag=false;
if(timeDiffer<150){
//时间间隔小于150,那么就判断为单击事件,这里时间间隔可自由设置
this.isClick=true;
}else{
this.isClick=false;
//拖拽结束,如果这里parent移出了grand边界,该怎么办呢?
获取完整代码,请加我的WX :
}
}
},
/**
* @breif 监听鼠标移出横向菜单栏
* ***/
leave(){
this.isDrag=false;
//鼠标移出菜单栏范围,这里操作属于锦上添花,完善功能
获取完整代码,请加我的WX :
},
clickDoSome(index){
if(this.isClick){
dosome
}
}
通过判断鼠标左键按下和抬起的时间间隔来判断是否为单击还是拖拽中
如果想获取完整代码,请加微信,前几天我查看了很多相关资料,自己找到了一个完美的解决办法,