vue将弹框抽离成组件(vue3 可拖动的左右面板分割组件实现)
类别:编程学习 浏览量:730
时间:2022-01-17 01:50:17 vue将弹框抽离成组件
vue3 可拖动的左右面板分割组件实现目录
- 分解组件
- 左侧面板
- 右侧面板
- 入参分解
- props
- slots
- 具体实现
- 如何拖动呢?
- 事件监听
- 宽度处理
- 优化
- bug
- git地址
最近在使用vue的时候,遇到一个需求,实现左右li可通过中间部分拖拽调整宽度,本文就整理一下,分享给大家,具体如下:
效果图
分解组件整体使用flex布局
左侧面板
- 面板的具体内容通过slot具名插槽传入。
- title通过prop传入
- 可拖动,为了保证内容样式不会被拖动所破坏,对面板的宽度设定最大值/最小值
右侧面板
- 右侧面板宽度随着左侧面板的宽度变化而变化,此处需注意,内容的宽度使用flex-auto自动适应。
- 需要做移动端的自适应。
- 自适应使用tailwind的媒体查询
props
- @param {Number} maxWidth 最大宽度
- @param {Number} minWidth 最小宽度
- @param {String} leftTitle 左标题
- @param {String} rightTitle 右标题?
- @param {Boolean} sotoreage 是否存储与localstorege
slots
- left-content {Element} 左侧内容
- right-content {Element} 右侧内容
如何拖动呢?
在左侧面板与右侧面板之间添加一个隐藏的盒子,我将这个盒子隐藏在box-shadow之中。具体事件放在这个li中实现
<li id="line" class="w-2 cursor-move hidden md4:block"onMousedown={hnadleMouseDown}> </li>
事件监听
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 baseli = document.querySelector(".right-border-shadow"); /* 处理宽度,是否处于最大值/最小值之间 */ let baseWidth: Number | undefined = Number(baseli?.clientWidth) + (pageX - basePosition.pageX); baseWidth = baseWidth > Number(props?.maxWidth) ? props.maxWidth : baseWidth; baseWidth = Number(baseWidth) < Number(props?.minWidth) ? props.minWidth : baseWidth; baseli?.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 可拖动左右分割面板内容请搜索开心学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持开心学习网!
您可能感兴趣
- vue虚拟滚动条(vue轻松实现虚拟滚动的示例代码)
- vue3.0零基础入门(快速掌握Vue3.0中如何上手Vuex状态管理)
- vue功能测试和生产环境切换(vue 单元测试的推荐插件和使用示例)
- vue子视图里再加routerview(vue router-view的嵌套显示实现)
- vue表单上传图片数据(vue-cropper插件实现图片截取上传组件封装)
- vue 单文件组件(vue实现一个单文件组件的完整过程记录)
- elementui和vue详解(Vue+Element UI实现概要小弹窗的全过程)
- vue实现树形结构菜单(vue递归实现三级菜单)
- vue怎么更换自定义水印(Vue之全局水印的实现示例)
- vue自定义列组件(vue自定义表格列的实现过程记录)
- vueelementui三级菜单(vue+element ui实现锚点定位)
- 小白vue教学(尤大大新活petite-vue的实现)
- vue 网页打印(vue打印功能实现的两种方法总结)
- vue离线地图有哪些(vue 集成腾讯地图实现api附DEMO)
- vue获取图片并展示(vue卡片式点击切换图片组件使用详解)
- vue怎么引入axios(如何用vue封装axios请求)
- 英语难学吗(法语比英语难学吗)
- 今天要吃什么(今天要吃什么菜好)
- 网红直播可以赚很多钱吗(网红直播可以赚很多钱吗)
- 今天是什么日子(今天是什么日子有什么特殊意义吗)
- 这里输入关键词(怎么输入关键词搜索)
- 34岁的舒畅,就这样走到了末路,不知会不会后悔15年前的草率决定(就这样走到了末路)
热门推荐
- 虚拟主机是搭建网站吗(电商网站选择虚拟主机的教程)
- SQLite数据类型
- php教程7.10.6学习(php5.6.x到php7.0.x特性小结)
- linux系统的pwd命令单词全称(WDCP是什么?Linux服务器管理系统WDCP有什么用?)
- java连接mongodb(Docker连接mongodb实现过程及代码案例)
- SQL处理字符串的函数
- mysql将字符串转换成整数(MYSQL字符串强转的方法示例)
- dedecms滚动代码(dedecms使用sql语句调用文章静态链接地址的方法)
- php中如何打开文件读文件(PHP通过文件保存和更新信息的方法分析)
- dockercp用法详解(Docker开启TLS和CA认证的方法步骤)