2021.9.28
坑93(vue3、拖拽边缘调整侧边栏宽度、拖拽条组件、宽度限制):目标是实现可拖动调整大小的右侧边栏。
重要参考: 模板引用 | Vue.js (vuejs.org)
预计通过ref、emit实现,分离拖拽条组件和侧边栏组件。
(考虑过将拖拽条组件写在侧边栏组件内,与原侧边栏组件并列,这样就无需通过父组件获取ref,但会提示非根组件的@mousedown可能无效果)
参考:vue组件间通信六种方式(完整版) - SegmentFault 思否
Vue3.0:如何在父组件中调用ref的子组件方法 - 平民的麦田 - 博客园 (cnblogs.com)
因为左侧放置的el-table对侧栏的挤压(具体挤压情况还要看el-table中的数据量),无法随意调整侧栏大小,通过style设置的width不一定能起作用。另外非内联设置width时,style中各值是空字符串。
参考: vue通过$ref获取不到元素样式? - SegmentFault 思否
也有方法不受el-table影响,即同时设置style.width、style.minWidth、style.maxWidth。这样可以任意更改大小。但这样当鼠标移动到父组件外时也会无限增加宽度(减小的话减到0就小不了)。所以最好设置一下上下限。
具体代码如下:
// 目标右侧栏组件中
const editBoxRef=ref(null)
const addBoxWidth=(addWidth)=>{
// ------------------------------未对宽限制大小时------------------------------
// 非内联设置width时,style中各值是空字符串
// 并且style.width获取的是设定宽,不一定等于offsetWidth实际宽(比如受左侧el-table挤压影响时)
editBoxRef.value.style.width=(editBoxRef.value.offsetWidth+addWidth+'px')
// 可以通过style.minWidth、style.maxWidth强制宽度大小,使其不受el-table挤压影响
// 相反,这样能挤压el-table
// editBoxRef.value.style.minWidth=(editBoxRef.value.offsetWidth+addWidth+'px')
// editBoxRef.value.style.maxWidth=(editBoxRef.value.offsetWidth+addWidth+'px')
// ------------------------------对宽限制上下限,上限是浏览器窗体宽的一半------------------------------
// let targetWidth=editBoxRef.value.offsetWidth+addWidth<260 ? '260px'
: editBoxRef.value.offsetWidth+addWidth>window.innerWidth/2 ? window.innerWidth/2+'px'
: editBoxRef.value.offsetWidth+addWidth+'px'
// 或者用封装了的函数limitNumberValue,具体实现见最下
// let targetWidth=limitNumberValue(editBoxRef.value.offsetWidth+addWidth,
{min:260,max:window.innerWidth/2})+'px'
// editBoxRef.value.style.width=editBoxRef.value.style.minWidth=editBoxRef.value.style.maxWidth=targetWidth
}
return {
editBoxRef,
addBoxWidth,
}
.editBox{
// 初始值
width: 350px;
min-width: 350px;
max-width: 350px;
height: 100%;
overflow: auto;
margin-left: 2px;
}
// dragStrip.vue 拖拽条
<template>
<div class='dragStripBox' @mousedown="startMove"></div>
</template>
<script>
export default {
name: 'DragStrip',
emits:[
'moved'
],
setup(props,{ emit }){
const startMove=(se)=>{
let startX=se.clientX
document.onmousemove=(ie)=>{
let endX=ie.clientX
let moveX=endX-startX // 左移负值,右移正值
startX=endX
emit('moved', moveX)// 发送moved事件
}
document.onmouseup=()=>{
document.onmousemove=document.onmouseup=null
}
}
return {
startMove,
}
}
}
</script>
<style scoped>
.dragStripBox {
background-color: #eeeeee;
width: 5px;
min-width: 5px;
cursor: ew-resize;
margin-left: 2px;
}
</style>
// 父组件中调用
<DragStrip @moved='handleMoved' />
<EditBox ref='editRef' />
const editRef=ref(null)
const handleMoved=(moveX)=>{
editRef.value.addBoxWidth(-moveX)
}
写了一个工具方法,方便调用:
// utils.js
// 限制某Number变量的最大最小值
export function limitNumberValue(number,{min,max}={}){
if( typeof min !== 'number' || typeof max !== 'number'){
return number
}
return number<min ? min
: number>max ? max
: number
}
参考:
Vue---拖动侧边栏改变div宽度_CRUSH_BUDS的博客-CSDN博客
拖拽一侧可以改变盒子宽度或者高度,拿来即用。_段友吊缠腰的博客-CSDN博客
vue中实现拖动调整左右两侧div的宽度_小咸肉、的博客-CSDN博客_vue 拖动div宽度
vue 自定义拖拉宽度变大变小,侧栏可拖拽改变大小,右边自动适应剩余宽度写自定义目录标题_舞空~的博客-CSDN博客
by 莫得感情踩坑机(限定)