记录生活中的点滴,分享、学习、创新
最近在使用vue的时候,遇到一个需求,实现左右div可通过中间部分拖拽调整宽度,本文就整理一下,分享给大家,具体如下:
效果图
整体使用flex布局
在左侧面板与右侧面板之间添加一个隐藏的盒子,我将这个盒子隐藏在box-shadow之中。具体事件放在这个div中实现
1 2 | < div id = "line" class = "w-2 cursor-move hidden md4:block" onMousedown={hnadleMouseDown}> </ div > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | const hnadleMouseDown = (evt: MouseEvent) => { /* 获取起始点位,并存储 */ let { pageX, pageY } = evt; basePosition.pageX = pageX; basePosition.pageY = pageY; /* 监听鼠标的移动事件 */ document.addEventListener( "mousemove" , handleMouseMove); document.addEventListener( "mouseup" , handleMouseUp); }; const handleMouseMove = evt => { /* 阻止浏览器默认事件,防止触发浏览器的手势功能 */ evt.preventDefault(); /* 设置定时器,防止dom多次回流 */ clearTimeout(timer.value); timer.value = setTimeout(() => { let { pageX } = evt; const baseDiv = document.querySelector( ".right-border-shadow" ); /* 处理宽度,是否处于最大值/最小值之间 */ let baseWidth: Number | undefined = Number(baseDiv?.clientWidth) + (pageX - basePosition.pageX); baseWidth = baseWidth > Number(props?.maxWidth) ? props.maxWidth : baseWidth; baseWidth = Number(baseWidth) < Number(props?.minWidth) ? props.minWidth : baseWidth; baseDiv?.setAttribute( "style" , `width:${baseWidth}px`); /* emit宽度改变的事件 */ ctx.emit( "drugend" ); /* 存储到store */ setStore(baseWidth); }, 50); }; const handleMouseUp = evt => { /* 结束拖动之后,取消事件监听,并emit出最终宽度 */ const width = document.querySelector( ".right-border-shadow" )?.clientWidth; document.removeEventListener( "mousemove" , handleMouseMove); document.removeEventListener( "mouseup" , handleMouseUp); ctx.emit( "drugend" , width); }; |
1 2 3 4 5 6 7 | style={` width :${ store.get( "split-width" ) ? store.get( "split-width" ) : props.minWidth ? props.minWidth : 384 }px`} |
手动改变浏览器视窗宽度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | nextTick(() => { ctx.emit( "load" , ctx); MutationObserver = window.MutationObserver; if (MutationObserver) { /* 监听浏览器的窗口变化,在部分情况下需要这个api */ mo = new MutationObserver( function () { const __wm = document.querySelector( "#rezie-id" ); // 只在__wm元素变动才重新调用 __canvasWM if (!__wm) { // 避免一直触发 mo.disconnect(); mo = null ; ctx.emit( "resize" ); } }); mo.observe(document.querySelector( "#rezie-id" ), { attributes: true , subtree: true , childList: true , }); } }); |
未生效,求指点
父组件的onMounted钩子中获取子元素的slot元素节点报错,为null。目前的解决办法是在子组件的onMounted钩子中抛出一个load事件,父组件使用onLoad去处理接下来的逻辑。