重庆网站建设找珊瑚云,专做公司网站 大庆,网站已经备案更换主机,沈阳医疗网站制作Vue实现可拖拽边界布局
在前端开发中#xff0c;有时需要实现一种可拖拽边界的布局#xff0c;通过拖动分隔线来调整不同区域大小。例如#xff0c;下图是一个典型的可拖拽边界布局#xff0c;它由左右两个区域组成#xff0c;左边是一个树形菜单#xff0c;右边是一个上…Vue实现可拖拽边界布局
在前端开发中有时需要实现一种可拖拽边界的布局通过拖动分隔线来调整不同区域大小。例如下图是一个典型的可拖拽边界布局它由左右两个区域组成左边是一个树形菜单右边是一个上下分割的内容区域。用户可以通过拖动水平和垂直的分隔线来改变左右区域和上下区域的宽度和高度。
本文用Vue来实现这种可拖拽边界布局只需要用到Vue的基本特性如数据绑定、事件处理、样式绑定等额外的el-tree基于elementui可不加。主要涉及到以下几个方面
布局结构使用flex布局来实现容器和子元素的分配使用style绑定来动态调整区域的大小使用cursor属性来改变鼠标的形状。数据定义使用data选项来定义不同区域的宽度和高度以及是否正在拖动分隔线以及拖动开始时的鼠标位置和区域大小。事件处理使用methods选项来定义开始拖动、拖动中和结束拖动的函数使用draggingH和draggingV来判断拖动的方向使用startX和startY来记录拖动的起点使用delta来计算拖动的距离使用leftWidth、rightWidth、topHeight和bottomHeight来更新区域的大小。事件绑定使用v-on指令来绑定分隔线的mousedown事件表示用户开始拖动分隔线给document绑定mousemove事件表示用户正在拖动分隔线给document绑定mouseup事件表示用户结束拖动分隔线。
布局结构
首先定义布局的结构这里使用flex布局来实现。布局由一个容器div和四个子div组成分别是左边区域、右边区域、水平分隔线和垂直分隔线。容器div的display属性设置为flex表示它是一个弹性盒子它的子元素可以按照一定的比例分配空间。左边区域和右边区域的flex-direction属性设置为column表示它们是一个垂直方向的弹性盒子它们的子元素可以按照一定的比例分配高度。右边区域又由上下两个子div组成分别是上面区域和下面区域。水平分隔线和垂直分隔线的宽度和高度分别设置为10px表示它们是分隔线的宽度。水平分隔线的cursor属性设置为col-resize表示当鼠标移动到分隔线上时鼠标的形状会变成一个水平方向的双箭头表示可以拖动分隔线。垂直分隔线的cursor属性设置为row-resize表示当鼠标移动到分隔线上时鼠标的形状会变成一个垂直方向的双箭头表示可以拖动分隔线。我们还可以给分隔线添加一些样式如背景色、边框等以增加视觉效果。以下是布局结构的代码
templatediv idappdiv classcontainerdiv classleft :style{ width: leftWidth px }el-tree classtree :datatreeData :propsdefaultProps node-keyid/el-tree/divdiv classdivider-h mousedownstartDragHspan||/span/divdiv classright :style{ width: rightWidth px }div classtop :style{ height: topHeight px }p这是右边上面的区域/p/divdiv classdivider-v mousedownstartDragV!-- span/span --/divdiv classbottom :style{ height: bottomHeight px }p这是右边下面的区域/p/div/div/div/div
/template数据定义
接下来定义一些数据用来表示不同区域的宽度和高度以及是否正在拖动分隔线以及拖动开始时的鼠标位置和区域大小。我们可以在Vue实例的data选项中定义这些数据如下所示
export default {name: App,data() {return {containerWidth: 800, // 容器的宽度containerHeight: 600, // 容器的高度leftWidth: 400, // 左边区域的宽度rightWidth: 400, // 右边区域的宽度topHeight: 300, // 右边上面区域的高度bottomHeight: 300, // 右边下面区域的高度draggingH: false, // 是否正在水平拖动draggingV: false, // 是否正在垂直拖动startX: 0, // 水平拖动开始时的鼠标位置startY: 0, // 垂直拖动开始时的鼠标位置startLeftWidth: 0, // 水平拖动开始时的左边区域宽度startRightWidth: 0,startTopHeight: 0, // 垂直拖动开始时的右边上面区域高度startBottomHeight: 0,};},
};事件处理
然后需要定义一些事件处理函数用来实现拖动分隔线的逻辑。监听分隔线的mousedown事件表示用户开始拖动分隔线以及document的mousemove事件表示用户正在拖动分隔线以及document的mouseup事件表示用户结束拖动分隔线。我们可以在Vue实例的methods选项中定义这些事件处理函数如下所示
methods: {// 开始水平拖动startDragH(e) {this.draggingH true;this.startX e.clientX;this.startLeftWidth this.leftWidth;this.startRightWidth this.rightWidth;},// 开始垂直拖动startDragV(e) {this.draggingV true;this.startY e.clientY;this.startTopHeight this.topHeight;this.startBottomHeight this.bottomHeight;},// 拖动中onDrag(e) {if (this.draggingH) {let delta e.clientX - this.startX;// 更新左右区域的宽度this.leftWidth this.startLeftWidth delta;this.rightWidth this.startRightWidth - delta;}if (this.draggingV) {let delta e.clientY - this.startY;// 更新上下区域的高度this.topHeight this.startTopHeight delta;this.bottomHeight this.startBottomHeight - delta;}},// 结束拖动endDrag() {this.draggingH false;this.draggingV false;},},在开始水平拖动和开始垂直拖动的函数中设置draggingH和draggingV为true表示正在拖动分隔线同时记录下鼠标的位置和区域的大小作为拖动的起点。在拖动中的函数中我们需要根据鼠标的位置和拖动的起点计算出拖动的距离然后根据拖动的距离更新左右区域和上下区域的宽度和高度。在结束拖动的函数中我们需要设置draggingH和draggingV为false表示停止拖动分隔线。
事件绑定
最后给水平分隔线和垂直分隔线绑定mousedown事件表示用户开始拖动分隔线给document绑定mousemove事件 mounted() {// 监听鼠标移动和松开事件document.addEventListener(mousemove, this.onDrag);document.addEventListener(mouseup, this.endDrag);},beforeDestroy() {// 移除事件监听document.removeEventListener(mousemove, this.onDrag);document.removeEventListener(mouseup, this.endDrag);},
};样式定义
最后我们需要给布局的元素添加一些样式以增加辨识度。我们可以在Vue实例的style选项中定义这些样式
完整代码
以下是完整的代码你可以复制到编辑器中运行
templatediv idappdiv classcontainerdiv classleft :style{ width: leftWidth px }el-tree classtree :datatreeData :propsdefaultProps node-keyid/el-tree/divdiv classdivider-h mousedownstartDragHspan||/span/divdiv classright :style{ width: rightWidth px }div classtop :style{ height: topHeight px }p这是右边上面的区域/p/divdiv classdivider-v mousedownstartDragV!-- span/span --/divdiv classbottom :style{ height: bottomHeight px }p这是右边下面的区域/p/div/div/div/div
/templatescript
export default {name: App,data() {return {containerWidth: 800, // 容器的宽度containerHeight: 600, // 容器的高度leftWidth: 400, // 左边区域的宽度rightWidth: 400, // 右边区域的宽度topHeight: 300, // 右边上面区域的高度bottomHeight: 300, // 右边下面区域的高度draggingH: false, // 是否正在水平拖动draggingV: false, // 是否正在垂直拖动startX: 0, // 水平拖动开始时的鼠标位置startY: 0, // 垂直拖动开始时的鼠标位置startLeftWidth: 0, // 水平拖动开始时的左边区域宽度startRightWidth: 0,startTopHeight: 0, // 垂直拖动开始时的右边上面区域高度startBottomHeight: 0,treeData: [{id: 1,label: 一级 1,children: [{id: 4,label: 二级 1-1,children: [{id: 9,label: 三级 1-1-1,},{id: 10,label: 三级 1-1-2,},],},],},{id: 2,label: 一级 2,children: [{id: 5,label: 二级 2-1,},{id: 6,label: 二级 2-2,},],},{id: 3,label: 一级 3,children: [{id: 7,label: 二级 3-1,},{id: 8,label: 二级 3-2,},],},],defaultProps: {children: children,label: label,},};},methods: {// 开始水平拖动startDragH(e) {this.draggingH true;this.startX e.clientX;this.startLeftWidth this.leftWidth;this.startRightWidth this.rightWidth;},// 开始垂直拖动startDragV(e) {this.draggingV true;this.startY e.clientY;this.startTopHeight this.topHeight;this.startBottomHeight this.bottomHeight;},// 拖动中onDrag(e) {if (this.draggingH) {// 计算水平拖动的距离let delta e.clientX - this.startX;// 更新左右区域的宽度this.leftWidth this.startLeftWidth delta;this.rightWidth this.startRightWidth - delta;}if (this.draggingV) {// 计算垂直拖动的距离let delta e.clientY - this.startY;// 更新上下区域的高度this.topHeight this.startTopHeight delta;this.bottomHeight this.startBottomHeight - delta;}},// 结束拖动endDrag() {this.draggingH false;this.draggingV false;},onresize() {this.leftWidth window.innerWidth * 0.3 - 5this.rightWidth window.innerWidth * 0.7 - 5this.topHeight window.innerHeight * 0.5 - 5this.bottomHeight window.innerHeight * 0.5 - 5console.log(window.screen);}},mounted() {// 监听鼠标移动和松开事件document.addEventListener(mousemove, this.onDrag);document.addEventListener(mouseup, this.endDrag);window.addEventListener(resize, this.onresize);this.leftWidth window.innerWidth * 0.2 - 5this.rightWidth window.innerWidth * 0.8 - 5this.topHeight window.innerHeight * 0.5 - 5this.bottomHeight window.innerHeight * 0.5 - 5// },beforeDestroy() {// 移除事件监听document.removeEventListener(mousemove, this.onDrag);document.removeEventListener(mouseup, this.endDrag);},
};
/scriptstyle
html,
body {width: 100%;height: 100%;margin: 0;padding: 0;
}.container {display: flex;width: 100%;height: 100%;/* border: 1px solid black; */
}.left {display: flex;flex-direction: column;background-color: lightblue;height: 100%;width: 30%;
}.right {display: flex;flex-direction: column;background-color: lightgreen;height: 100%;width: 70%;}.top {background-color: blueviolet;
}.bottom {background-color: bisque;
}.divider-h {width: 10px;cursor: col-resize;
}.divider-h span {display: block;margin-top: 290px;
}.divider-v {height: 10px;cursor: row-resize;background-color: aliceblue;
}.divider-v span {display: block;margin-left: 190px;
}.tree {flex: 1;overflow: auto;cursor: pointer;
}/style 文章转载自: http://www.morning.ykmtz.cn.gov.cn.ykmtz.cn http://www.morning.lxfqc.cn.gov.cn.lxfqc.cn http://www.morning.knpbr.cn.gov.cn.knpbr.cn http://www.morning.cryb.cn.gov.cn.cryb.cn http://www.morning.qbzdj.cn.gov.cn.qbzdj.cn http://www.morning.zzfqn.cn.gov.cn.zzfqn.cn http://www.morning.gbsfs.com.gov.cn.gbsfs.com http://www.morning.nhlyl.cn.gov.cn.nhlyl.cn http://www.morning.ykbgs.cn.gov.cn.ykbgs.cn http://www.morning.mgnrc.cn.gov.cn.mgnrc.cn http://www.morning.srrrz.cn.gov.cn.srrrz.cn http://www.morning.rcrfz.cn.gov.cn.rcrfz.cn http://www.morning.reababy.com.gov.cn.reababy.com http://www.morning.pprxs.cn.gov.cn.pprxs.cn http://www.morning.qywfw.cn.gov.cn.qywfw.cn http://www.morning.rwjtf.cn.gov.cn.rwjtf.cn http://www.morning.rqxch.cn.gov.cn.rqxch.cn http://www.morning.skscy.cn.gov.cn.skscy.cn http://www.morning.trtxt.cn.gov.cn.trtxt.cn http://www.morning.tpnx.cn.gov.cn.tpnx.cn http://www.morning.lwnwl.cn.gov.cn.lwnwl.cn http://www.morning.jzykw.cn.gov.cn.jzykw.cn http://www.morning.qtyfb.cn.gov.cn.qtyfb.cn http://www.morning.gyjld.cn.gov.cn.gyjld.cn http://www.morning.pkmw.cn.gov.cn.pkmw.cn http://www.morning.yrkdq.cn.gov.cn.yrkdq.cn http://www.morning.dwfxl.cn.gov.cn.dwfxl.cn http://www.morning.wslr.cn.gov.cn.wslr.cn http://www.morning.sxtdh.com.gov.cn.sxtdh.com http://www.morning.kclkb.cn.gov.cn.kclkb.cn http://www.morning.nyzmm.cn.gov.cn.nyzmm.cn http://www.morning.mksny.cn.gov.cn.mksny.cn http://www.morning.rqjl.cn.gov.cn.rqjl.cn http://www.morning.xkjrs.cn.gov.cn.xkjrs.cn http://www.morning.jgzmr.cn.gov.cn.jgzmr.cn http://www.morning.wtdhm.cn.gov.cn.wtdhm.cn http://www.morning.tkchm.cn.gov.cn.tkchm.cn http://www.morning.bhgnj.cn.gov.cn.bhgnj.cn http://www.morning.tjjkn.cn.gov.cn.tjjkn.cn http://www.morning.wjjxr.cn.gov.cn.wjjxr.cn http://www.morning.rngyq.cn.gov.cn.rngyq.cn http://www.morning.cljmx.cn.gov.cn.cljmx.cn http://www.morning.dsprl.cn.gov.cn.dsprl.cn http://www.morning.dpruuode.cn.gov.cn.dpruuode.cn http://www.morning.wxccm.cn.gov.cn.wxccm.cn http://www.morning.jrqw.cn.gov.cn.jrqw.cn http://www.morning.fnkcg.cn.gov.cn.fnkcg.cn http://www.morning.c7625.cn.gov.cn.c7625.cn http://www.morning.rnlx.cn.gov.cn.rnlx.cn http://www.morning.sgjw.cn.gov.cn.sgjw.cn http://www.morning.pyswr.cn.gov.cn.pyswr.cn http://www.morning.yggdq.cn.gov.cn.yggdq.cn http://www.morning.jcrfm.cn.gov.cn.jcrfm.cn http://www.morning.gthc.cn.gov.cn.gthc.cn http://www.morning.srgyj.cn.gov.cn.srgyj.cn http://www.morning.ffwrq.cn.gov.cn.ffwrq.cn http://www.morning.rbmm.cn.gov.cn.rbmm.cn http://www.morning.qkqgj.cn.gov.cn.qkqgj.cn http://www.morning.bby45.cn.gov.cn.bby45.cn http://www.morning.flmxl.cn.gov.cn.flmxl.cn http://www.morning.mzhgf.cn.gov.cn.mzhgf.cn http://www.morning.smxyw.cn.gov.cn.smxyw.cn http://www.morning.kdjtt.cn.gov.cn.kdjtt.cn http://www.morning.gfmpk.cn.gov.cn.gfmpk.cn http://www.morning.mwzt.cn.gov.cn.mwzt.cn http://www.morning.hlfgm.cn.gov.cn.hlfgm.cn http://www.morning.yrbhf.cn.gov.cn.yrbhf.cn http://www.morning.zcsch.cn.gov.cn.zcsch.cn http://www.morning.bwdnx.cn.gov.cn.bwdnx.cn http://www.morning.qrwnj.cn.gov.cn.qrwnj.cn http://www.morning.qsxxl.cn.gov.cn.qsxxl.cn http://www.morning.xbckm.cn.gov.cn.xbckm.cn http://www.morning.yqsr.cn.gov.cn.yqsr.cn http://www.morning.nsrlb.cn.gov.cn.nsrlb.cn http://www.morning.nqlkb.cn.gov.cn.nqlkb.cn http://www.morning.rfgkf.cn.gov.cn.rfgkf.cn http://www.morning.bnlsd.cn.gov.cn.bnlsd.cn http://www.morning.brld.cn.gov.cn.brld.cn http://www.morning.bnxnq.cn.gov.cn.bnxnq.cn http://www.morning.qzxb.cn.gov.cn.qzxb.cn