vue3 可拖动的左右面板分割组件实现
最近在使用vue的时候,遇到一个需求,实现左右div可通过中间部分拖拽调整宽度,本文就整理一下,分享给大家,具体如下:
效果图
整体使用flex布局
左侧面板 面板的具体内容通过slot具名插槽传入。 title通过prop传入 可拖动,为了保证内容样式不会被拖动所破坏,对面板的宽度设定最大值/最小值右侧面板 右侧面板宽度随着左侧面板的宽度变化而变化,此处需注意,内容的宽度使用flex-auto自动适应。 需要做移动端的自适应。 自适应使用tailwind的媒体查询在左侧面板与右侧面板之间添加一个隐藏的盒子,我将这个盒子隐藏在box-shadow之中。具体事件放在这个div中实现
<div class='w-2 cursor-move hidden md4:block'onMousedown={hnadleMouseDown}></div>事件监听
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); };宽度处理
style={`width:${ store.get('split-width') ? store.get('split-width') : props.minWidth ? props.minWidth : 384 }px`}优化
手动改变浏览器视窗宽度
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, });} });
未生效,求指点
bug父组件的onMounted钩子中获取子元素的slot元素节点报错,为null。目前的解决办法是在子组件的onMounted钩子中抛出一个load事件,父组件使用onLoad去处理接下来的逻辑。
git地址仓库地址预览地址
到此这篇关于vue3 可拖动的左右面板分割组件实现的文章就介绍到这了,更多相关vue3 可拖动左右分割面板内容请搜索好吧啦网以前的文章或继续浏览下面的相关文章希望大家以后多多支持好吧啦网!
相关文章:
1. django创建css文件夹的具体方法2. jsp网页实现贪吃蛇小游戏3. phpstudy apache开启ssi使用详解4. ASP中if语句、select 、while循环的使用方法5. MyBatis JdbcType 与Oracle、MySql数据类型对应关系说明6. ASP中实现字符部位类似.NET里String对象的PadLeft和PadRight函数7. .NET SkiaSharp 生成二维码验证码及指定区域截取方法实现8. Django model重写save方法及update踩坑详解9. CentOS邮件服务器搭建系列—— POP / IMAP 服务器的构建( Dovecot )10. 存储于xml中需要的HTML转义代码
