当前位置: 首页 > news >正文

Element plus 低版本弹窗组件添加拖拽功能

        在使用element plus 弹窗组件el-dialog 的时候,由于自己组件库版本过低,所以就会缺失某些功能,比如弹窗组件的可拖拽功能。因为某些原因element plus 组件库又不能升级,所以此时就需要自己为弹窗组件添加拖拽功能。共分为一下四个步骤

  1. 在全局状态管理中添加两个属性,dialogDom 用于保存弹窗dom,visible, 用于保存弹窗组件的props.visible便于插件根据弹窗的开关状态进行事件的绑定和解除。
  2. 在自己的弹窗组件中的el-dialog 的标签中添加ref,并监听props.visible 。当弹窗打开时将弹窗的dom,及props.visible,存入全局状态管理的新增属性中。
  3. 自定义插件,编写拖拽功能

    插件中使用watch,只能执行一次,并不能监听store.visible 的改变。所以使用Object.defineProperty,监听store.visible

  4. 安装插件。app.use();
/** @Description:弹窗过拽插件* @Author: zhangyuqi* @Date: 2024-05-27 11:01:01* @LastEditors: zhangyuqi* @LastEditTime: 2024-05-27 17:41:00* @FilePath: \idata-micro\src\plugins\dialog-drag.ts*/
import { App, reactive, ref } from 'vue';
import dataReportStore from '@/store/modules/data-report';export default {install(app:App) {let dialogVisible = dataReportStore.state.visible as Boolean;const myDialogDom = ref <any>(dataReportStore.state.dialogDom);const state = reactive({active: false,top: 0,left: 0,right: 0,bottom: 0,currentX: 0,currentY: 0,initialX: 0,initialY: 0,transformX: 0,transformY: 0,});// 鼠标进入触发方法const mouseEnter = (event:MouseEvent) => {// 鼠标进入修改弹窗元素鼠标形状if (myDialogDom.value) {// eslint-disable-next-line no-param-reassignmyDialogDom.value.firstElementChild.style.cursor = 'move';}};// 鼠标按下触发方法const mouseDown = (event:MouseEvent) => {// 鼠标进入修改弹窗元素鼠标形状if (myDialogDom.value) {event.preventDefault();// 获取元素宽高const { left, right, top, bottom } = myDialogDom.value.getBoundingClientRect();state.top = top;state.left = left;state.right = right;state.bottom = bottom;if (myDialogDom.value?.style.transform) {// 此时弹窗已经被拖拽过,存在偏移量,所计算的值应在当前偏移量上进行累加const str = myDialogDom.value.style.transform;const regExp = /-?\d+(?:\.\d+)?/g;const result = str.match(regExp) as any;state.transformX = Number(result[0]);state.transformY = Number(result[1]);state.bottom -= state.transformY;state.left -= state.transformX;state.right -= state.transformX;state.top -= state.transformY;}// eslint-disable-next-line no-param-reassignstate.initialX = event.clientX;state.initialY = event.clientY;// }state.active = true;}};// 鼠标按下触发方法const mouseUp = () => {// 鼠标进入修改弹窗元素鼠标形状if (myDialogDom.value) {state.active = false;state.top = 0;state.bottom = 0;state.left = 0;state.right = 0;state.initialX = 0;state.initialY = 0;state.currentX = 0;state.currentY = 0;state.transformX = 0;state.transformY = 0;}};// 鼠标按下触发方法const mouseMove = (event:MouseEvent) => {// 鼠标进入修改弹窗元素鼠标形状if (state.active) {event.preventDefault();state.currentX = event.clientX - state.initialX + state.transformX;state.currentY = event.clientY - state.initialY + state.transformY;// 上边界if (state.currentY <= -state.top) state.currentY = -state.top;// 左边界if (state.currentX <= -state.left) state.currentX = -state.left;// 下边界if (state.currentY >= (window.innerHeight - state.bottom)) state.currentY = window.innerHeight - state.bottom;// 右边界if (state.currentX >= (window.innerWidth - state.right)) state.currentX = window.innerWidth - state.right;// eslint-disable-next-line no-param-reassignmyDialogDom.value.style.transform = `translate(${state.currentX}px, ${state.currentY}px)`;}};// 监听器函数const watcher = (newVal:Boolean) => {if (newVal) {myDialogDom.value = dataReportStore.state.dialogDom;if (myDialogDom.value) {myDialogDom.value.firstElementChild.addEventListener('mouseenter', mouseEnter);myDialogDom.value.firstElementChild.addEventListener('mousedown', mouseDown);myDialogDom.value.firstElementChild.addEventListener('mouseup', mouseUp);document.addEventListener('mouseup', mouseUp);document.addEventListener('mousemove', mouseMove);}// 当鼠标移入的时候,更改鼠标形态// 当鼠标按下时} else {const { dialogDom } = dataReportStore.state as any;if (dialogDom) {myDialogDom.value.firstElementChild.removeEventListener('mouseenter', mouseEnter);myDialogDom.value.firstElementChild.removeEventListener('mousedown', mouseDown);myDialogDom.value.firstElementChild.removeEventListener('mouseup', mouseUp);document.removeEventListener('mouseup', mouseUp);document.removeEventListener('mousemove', mouseMove);}}};Object.defineProperty(dataReportStore.state, 'visible', {get() {return dialogVisible;},set(val:Boolean) {dialogVisible = val;watcher(val);},});},
};

注释:

  1. mouseenter,mousedown,mouseup方法都绑定在弹窗的header 部分的dom元素上。因为事件触发需要使用event.preventDefault()来清楚鼠标默认事件 。如果这三个鼠标事件绑定在弹窗整体元素上,调用event.preventDefault()之后,弹窗内的输入框等元素的功能就无法正常使用了。
  2. mouseup,mousemove事件绑定在document上,因为当鼠标拖拽弹窗在窗口边缘时,只要不松手,拖拽依然在窗口内是有效果的。如果没有绑定到document上,如果将弹窗拖拽至窗口上边缘,此时鼠标移出窗口范围至浏览器边框时,松手,再移会窗口。此时弹窗仍然会根据鼠标进行移动,这样是不对的。
http://www.lryc.cn/news/355492.html

相关文章:

  • 计算机组成原理易混淆知识点总结(持续更新)
  • 【STM32踩坑】HAL固件库版本过高导致烧录后无法运行问题
  • 芯片丝印反查
  • C语言之指针详解(5)(含有易错笔试题)
  • discuzX2.5的使用心得 札记一
  • 【Python】 探索Django框架的高并发处理能力
  • C-数据结构-平横二叉树
  • 算法训练营day41
  • cesium开发实例分享
  • 字符串和字符串函数(1)
  • 基于springboot+vue的班级综合测评管理系统
  • 蓝海项目揭秘:跨境选品师的崛起与挑战
  • 酷黑简洁大气体育直播自适应模板赛事直播门户网站源码
  • 2024年电工杯高校数学建模竞赛(B题) 建模解析| 大学生平衡膳食食谱的优化设计
  • 学习编程对英语要求高吗?
  • 使用 Django 和 RabbitMQ 构建高效的消息队列系统
  • Pycharm常见问题1
  • 开发一个comfyui的自定义节点
  • Prime算法构造最小生成树(加点法)
  • 【VTKExamples::Utilities】第五期 CommandSubclass
  • 重生之 SpringBoot3 入门保姆级学习(04、 包扫描)
  • VectorDBBench在windows的调试
  • KAN(Kolmogorov-Arnold Network)的理解 1
  • Vue 项目中使用 Element UI库(Element UI 是一套基于 Vue.js 的桌面端组件库)
  • C++240527
  • 揭秘动态网页爬取:步骤与实战技巧
  • Lvm逻辑卷调整容量
  • CLIP源码详解:clip.py 文件
  • linux下重启oracle数据库步骤
  • [自动驾驶技术]-1 概述技术和法规