这里是直接完整一个组件,路由引入即可看到效果。
<template>
<div class="box" ref="box">
<div class="left">
<!--左侧div内容-->
<h1>到了时间你就一定要上场</h1>
<h1>当意识到达,那就必须上岸</h1>
</div>
<div class="resize" title="收缩侧边栏"></div>
<div class="mid">
<!--右侧div内容-->
<h1>我希望我希望的有希望</h1>
<h1>想着光向着光</h1>
</div>
</div>
</template>
<script> export default { data() { return {}; }, methods: { dragControllerDiv() { var resize = document.getElementsByClassName("resize")[0]; var left = document.getElementsByClassName("left"); var mid = document.getElementsByClassName("mid"); var box = document.getElementsByClassName("box")[0]; // 鼠标按下事件
resize.onmousedown = function (e) { //颜色改变提醒
resize.style.background = "#818181"; var startX = e.clientX; resize.left = resize.offsetLeft; // 鼠标拖动事件
document.onmousemove = function (e) { var endX = e.clientX; var moveLen = resize.left + (endX - startX); // (endx-startx)=移动的距离。resize.left+移动的距离=左边区域最后的宽度
var maxT = box.clientWidth - resize.offsetWidth; // 容器宽度 - 左边区域的宽度 = 右边区域的宽度
if (moveLen < 32) moveLen = 32; // 左边区域的最小宽度为32px
if (moveLen > maxT - 150) moveLen = maxT - 150; //右边区域最小宽度为150px
resize.style.left = moveLen; // 设置左侧区域的宽度
for (let j = 0; j < left.length; j++) { left[j].style.width = moveLen + "px"; mid[j].style.width = box.clientWidth - moveLen - 10 + "px"; } }; // 鼠标松开事件
document.onmouseup = function () { //颜色恢复
resize.style.background = "#d6d6d6"; document.onmousemove = null; document.onmouseup = null; resize.releaseCapture && resize.releaseCapture(); //当你不在需要继续获得鼠标消息就要应该调用ReleaseCapture()释放掉
}; resize.setCapture && resize.setCapture(); //该函数在属于当前线程的指定窗口里设置鼠标捕获
return false; }; }, }, mounted() { this.dragControllerDiv(); }, }; </script>
<style scoped>
/* 拖拽相关样式 */
/*包围div样式*/ .box { width: 100%; height: 50vh; margin: 5vh 0px; overflow: hidden; box-shadow: -1px 9px 10px 3px rgba(0, 0, 0, 0.11); } /*左侧div样式*/ .left { 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; } /*右侧div'样式*/ .mid { float: left; width: 68%; /*右侧初始化宽度*/ height: 100%; background: #fff; box-shadow: -1px 4px 5px 3px rgba(0, 0, 0, 0.11); } </style>
封装好的组件:(vue文件)
<template>
<div id="dragLayoutBox">
<div class="left_box">
<slot name="left-content"></slot>
</div>
<div class="right_box">
<div v-if="iframeIsHave" class="opacity_box"></div>
<div v-show="dragBtnFlag" class="drag_btn" @mousedown="changeBoxStyleFn('')" @onmouseup="changeBoxStyleFn('none')"
></div>
<slot name="right-content"> </slot>
</div>
</div>
</template>
<script> export default { props: { // 是否默认显示拖拽按钮
dragBtnFlag: { typeof: Boolean, default: true }, // 盒子中是否有iframme
iframeIsHave: { typeof: Boolean, default: false }, // 配置项 注意:色值暂时只支持16进制写法
setCssProps: { typeof: Object, default: () => ({ // 左右盒子最小拖动宽度
leftMinWidth: '200px', rightMinWidth: '500px', dragBtnCss: { mousedown: { background: '#919191' }, onmouseup: { background: '#d6d6d6' } } }) } }, mounted() { if (this.iframeIsHave) { this.changeBoxStyleFn('none') } this.dragChangeLayoutFn() }, methods: { getDomFn(name) { const ele = document.querySelector(name) const ws = new WeakSet() ws.add(ele) return ele }, changeBoxStyleFn(value) { if (this.iframeIsHave) { const opacityBox = this.getDomFn('.opacity_box') opacityBox.style.display = value } }, dragChangeLayoutFn() { const that = this const dragBtn = this.getDomFn('.drag_btn') const left_box = this.getDomFn('.left_box') const right_box = this.getDomFn('.right_box') const dragLayoutBox = this.getDomFn('#dragLayoutBox') dragBtn.onmousedown = function (e) { const styleStr = that.handleEleStyleFn(that.setCssProps.dragBtnCss.mousedown) dragBtn.style.cssText = `${styleStr}` const startPos = e.clientX dragBtn.left = dragBtn.offsetLeft document.onmousemove = e => { const endPos = e.clientX let moveW = dragBtn.left - 20 + (endPos - startPos) const maxW = dragLayoutBox.clientWidth - dragBtn.offsetWidth // 左边区域的最小宽度
const leftValue = parseInt(that.setCssProps.leftMinWidth) if (moveW < leftValue) { moveW = leftValue } // 右边区域最小宽度
const rightValue = parseInt(that.setCssProps.rightMinWidth) if (moveW > maxW - rightValue) { moveW = maxW - rightValue } left_box.style.cssText = `width:${moveW}px` right_box.style.width = dragLayoutBox.clientWidth - moveW + 'px' } document.onmouseup = () => { const styleStr = that.handleEleStyleFn(that.setCssProps.dragBtnCss.onmouseup) dragBtn.style.cssText = `${styleStr}` document.onmousemove = document.onmouseup = null
if (that.iframeIsHave) { that.changeBoxStyleFn('none') } dragBtn.releaseCapture && dragBtn.releaseCapture() } dragBtn.setCapture && dragBtn.setCapture() return false } }, // 处理传来的对象:{k1:"v1",k2:"v2"} => "k1:v1;k2:v2"
handleEleStyleFn(obj) { let str = JSON.stringify(obj) const indexstart = str.indexOf('{') const indexEnd = str.indexOf('}') str = str.slice(indexstart + 1).slice(0, indexEnd - 1) const reg1 = /,/g const reg2 = /"|'/g return str.replace(reg1, ';').replace(reg2, '') } } } </script>
<style scoped> #dragLayoutBox { width: 100%; display: flex; justify-content: space-between; box-shadow: 0px 20px 40px 0px rgba(0, 0, 0, 0.08); } .drag_btn { position: absolute; top: calc((100vh - 50px) / 2); width: 8px; height: 50px; cursor: col-resize; background: rgba(0, 0, 0, 0.1); border-radius: 5px; margin-top: -10px; background-size: cover; background-position: center; font-size: 32px; color: white; z-index: 1112; } .opacity_box { width: 100%; height: 100%; position: absolute; margin-top: 30px; filter: alpha(opacity=0); opacity: 0; background: transparent; z-index: 1111; } </style>
使用:
1.引入和注册
const LayoutDrag = () => import('./LayoutDrag/index.vue') components: { LayoutDrag }
2.使用:iframeIsHave为true表示右侧区域内有iframe,默认不传则为false,这个的判定就是为了解决当有iframe(比如富文本)拖拽时卡顿问题
<LayoutDrag :iframeIsHave="true">
<template v-slot:left-content>
// 你的左侧盒子的盛放区域
</template>
<template v-slot:right-content>
// 你的右侧盒子盛放区域
</template>
</LayoutDrag>