Element-UI实现el-dialog弹框拖拽功能

        在实际开发中,会发现有些系统,弹框是可以在浏览器的可见区域自由拖拽的,这极大方便用户的操作。但在查看Element-UI中弹框(el-dialog)组件的文档时,发现并未实现这一功能。不过也无须担心,vue中提供了Vue.directive钩子函数,可以从底层操作DOM来实现并升级弹框拖拽的功能。

        对于Vue.directive这里就不再阐述了,上一篇中已作了相关说明,不了解此功能的朋友可以翻看一上篇了解下,地址:Element-UI - 解决el-table中图片悬浮被遮挡问题-CSDN博客,或者去官方文档了解。另外,上篇是通过自定义指令的局部定义方式实现的,此篇将通过全局模式进行定义和开发。

一、演示页面创建

        首先我们在Vue项目中,创建一个页面用于演示拖拽功能的实现。代码如下:

<template><div><div class="right-box"><el-button type="primary" size="mini" @click="dialogVisible = true">新增</el-button></div><el-dialogtitle="提示":visible.sync="dialogVisible"width="30%"><span>这是一个弹框,升级其功能,能在浏览器可见区域自由拖拽</span><span slot="footer" class="dialog-footer"><el-button @click="dialogVisible = false">取 消</el-button><el-button type="primary" @click="dialogVisible = false">确 定</el-button></span></el-dialog></div>
</template><script>
export default {data(){return {dialogVisible: false}},
}
</script><style lang="less" scoped>
.right-box{text-align: right;padding-bottom: 15px;
}
</style>

        界面效果:

二、定义v-dialogDrag

        这里在Vue项目中src/utils目录中创建dialog.js,用来定义Vue-directive('dialogDrag', {});代码如下:

import Vue from 'vue'
/*** 新增弹框拖拽功能*/
Vue.directive('dialogDrag', {bind: (el) => {console.log('v-dialogDrag');}
})

        在main.js文件中引入dialog.js,代码如下:

import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import '@/utils/dialog.js'Vue.use(ElementUI)Vue.config.productionTip = false/* eslint-disable no-new */
new Vue({el: '#app',router,components: { App },template: '<App/>'
})

        页面中的el-dialog标签上添加v-dialogDrag,代码如下:

<template><div><div class="right-box"><el-button type="primary" size="mini" @click="dialogVisible = true">新增</el-button></div><el-dialogtitle="提示"v-dialogDrag:visible.sync="dialogVisible"width="30%"><span>这是一个弹框,升级其功能,能在浏览器可见区域自由拖拽</span><span slot="footer" class="dialog-footer"><el-button @click="dialogVisible = false">取 消</el-button><el-button type="primary" @click="dialogVisible = false">确 定</el-button></span></el-dialog></div>
</template>

        在定义v-dialogDrag时,在钩子函数中添加了控制台输出,bind是一次性的初始化设置,所以在组件绑定后只调用一次。此时查看控制台可以看到输出内容,如下图:

三、DOM操作

        在bind钩子函数中,将接收到的参数el输出查看可以发现,el为弹框的DOM节点。此时,我们就可以通过el节点获取到弹框标题.el-dialog__header部分,并对其进行事件监听,实现弹框拖拽功能。

3.1 修改鼠标样式

        修改弹框标题区域鼠标样式,当鼠标放到标题区域时呈现出移动图标,代码如下:

Vue.directive('dialogDrag', {bind: (el) => {// 获取弹框标题区域DOM节点const headerDOM = el.querySelector('.el-dialog__header');// 修改鼠标图标样式headerDOM.style.cursor = "move";// 禁止拖拽时选中标题中文本内容headerDOM.style.userSelect = "none";console.log('v-dialogDrag', el);}
})

3.2 添加监听事件

        对于拖拽功能会使用到onmousedown、onmousemove、onmouseup三个事件,分别对应鼠标按下、鼠标移动、鼠标松开三个动作。代码如下:

Vue.directive('dialogDrag', {bind: (el) => {// 获取弹框标题区域DOM节点const headerDOM = el.querySelector('.el-dialog__header');// 修改鼠标图标样式headerDOM.style.cursor = "move";// 禁止拖拽时选中标题中文本内容headerDOM.style.userSelect = "none";// 获取弹框区域的DOM节点const dialogDOM = el.querySelector('.el-dialog');let isDown = false;   //是否按下// 监听鼠标按下事件headerDOM.onmousedown = e => {isDown = true;console.log('mouse down', e);}// 监听鼠标移动事件headerDOM.onmousemove = e => {// 不按下的时候,执行移动操作if(isDown){console.log('mouse move', e);}}// 监听鼠标松开事件headerDOM.onmouseup = e => {console.log('mouse up', e);isDown = false;     //}}
})

        使用鼠标在住标题区域,进行按下、移动、松开等操作,查看控制台输出结果如下:

3.3 计算并重置弹框位置

        现在我们则可以通过获取相应的参数数据,对弹框进行位置计算,使其根据鼠标移动的位置进行拖拽了。代码如下:

Vue.directive('dialogDrag', {bind: (el) => {// 获取弹框标题区域DOM节点const headerDOM = el.querySelector('.el-dialog__header');// 修改鼠标图标样式headerDOM.style.cursor = "move";// 禁止拖拽时选中标题中文本内容headerDOM.style.userSelect = "none";// 获取弹框区域的DOM节点const dialogDOM = el.querySelector('.el-dialog');let isDown = false,         // 是否按下// 鼠标按下时坐标位置clientX = 0,clientY = 0,// 按下时弹框位置dialogLeft = 0,dialogTop = 0;// 监听鼠标按下事件headerDOM.onmousedown = e => {isDown = true;// 获取当前鼠标按钮位置坐标clientX = e.clientX;clientY = e.clientY;// 获取弹框位置(默认情况弹框样式left和top可能不存在,当为NaN时初始化为0)dialogLeft = isNaN(parseFloat(dialogDOM.style.left))?0:parseFloat(dialogDOM.style.left);dialogTop = isNaN(parseFloat(dialogDOM.style.top))?0:parseFloat(dialogDOM.style.top);}// 监听鼠标移动事件headerDOM.onmousemove = e => {// 不按下的时候,执行移动操作if(isDown){// 获取当前移动到的位置坐标,与按下位置坐标进行计算,获取移动距离const distX = e.clientX - clientX;const distY = e.clientY - clientY;// 修改弹框位置dialogDOM.style.left = (dialogLeft + distX) + "px";dialogDOM.style.top = (dialogTop + distY) + "px";}}headerDOM.onmouseup = () => isDown = false;         // 监听标题区域鼠标是否松开dialogDOM.onmouseleave = () => isDown = false;      // 监听鼠标是否移出弹框区域}
})

        以上对计算方法都代码中进行说明了,大家可根据解释进行实操并体会其中原理。以上功能实现后,弹框则可以通过按住标题区域进行拖放了。如下图:

3.4 限定区域

        当弹框拖拽功能实现后,会发现其有时会超出界面范围,并影响拖拽效果。对于这块,我们可以通过计算,来限定其可移动范围。

        之前我们学习过getBoundingClientRect()可获取DOM元素的边界信息,当left或top小于0时,则弹框已超出了顶部或者左侧可见区域,判断是否超过右侧或底部可见区域,则需要通过width和height,以及window.innerWidth和window.innerHeight结合计算得出结论。

        通过上述的分析,我们来定义一个函数用于判断当前时否可执行移动操作。代码如下:

// 定义函数判断当前是否在可见范围内
function boundingRange(){const bounding = dialogDOM.getBoundingClientRect();return {top: bounding.top >= 0,       // 表示顶部在可见范围left: bounding.left >= 0,     // 表示左侧在可见范围right: bounding.left <= window.innerWidth - bounding.width,   // 表示右侧在指定范围bottom: bounding.top < window.innerHeight - bounding.height   // 表示底部在指定范围}
}

        当添加到移动事件中并获取边界范围,通过获取的结果来判断是否为可操作状态。true为可操作,false为不可操作。如下图:

        此时,我们要在mousemove事件中对计算方式修改一下,最终完整代码如下:

Vue.directive('dialogDrag', {bind: (el) => {// 获取弹框标题区域DOM节点const headerDOM = el.querySelector('.el-dialog__header');// 修改鼠标图标样式headerDOM.style.cursor = "move";// 禁止拖拽时选中标题中文本内容headerDOM.style.userSelect = "none";// 获取弹框区域的DOM节点const dialogDOM = el.querySelector('.el-dialog');let isDown = false,         // 是否按下// 鼠标按下时坐标位置clientX = 0,clientY = 0,// 按下时弹框位置dialogLeft = 0,dialogTop = 0;// 定义函数判断当前是否在可见范围内function boundingRange(){const bounding = dialogDOM.getBoundingClientRect();return {top: bounding.top >= 0,       // 表示顶部在可见范围left: bounding.left >= 0,     // 表示左侧在可见范围right: bounding.left < window.innerWidth - bounding.width,   // 表示右侧在指定范围bottom: bounding.top < window.innerHeight - bounding.height   // 表示底部在指定范围}}// 监听鼠标按下事件headerDOM.onmousedown = e => {isDown = true;// 获取当前鼠标按钮位置坐标clientX = e.clientX;clientY = e.clientY;// 获取弹框位置(默认情况弹框样式left和top可能不存在,当为NaN时初始化为0)dialogLeft = isNaN(parseFloat(dialogDOM.style.left))?0:parseFloat(dialogDOM.style.left);dialogTop = isNaN(parseFloat(dialogDOM.style.top))?0:parseFloat(dialogDOM.style.top);}// 监听鼠标移动事件headerDOM.onmousemove = e => {// 不按下的时候,执行移动操作if(isDown){// 获取DOM边界范围const range = boundingRange();// 获取当前移动到的位置坐标,与按下位置坐标进行计算,获取移动距离const distX = e.clientX - clientX;          // distX小于0为向左,大于0为向右const distY = e.clientY - clientY;          // distY小于0为向上,大于0为向下// 判断左侧或右侧是否可移动if((range.left && distX < 0) || (range.right && distX >= 0)) dialogDOM.style.left = (dialogLeft + distX) + "px";// 判断顶部或者底部是否可移动if((range.top && distY < 0) || (range.bottom && distY >= 0)) dialogDOM.style.top = (dialogTop + distY) + "px";}}headerDOM.onmouseup = () => isDown = false;         // 监听标题区域鼠标是否松开dialogDOM.onmouseleave = () => isDown = false;      // 监听鼠标是否移出弹框区域}
})

        目前弹框的拖拽功能就已完成了,希望对大家有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/30868.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Day 28:2748. 美丽下标对的数目

Leetcode 2748. 美丽下标对的数目 给你一个下标从 0 开始的整数数组 nums 。如果下标对 i、j 满足 0 ≤ i < j < nums.length &#xff0c;如果 nums[i] 的 第一个数字 和 nums[j] 的 最后一个数字 互质 &#xff0c;则认为 nums[i] 和 nums[j] 是一组 美丽下标对 。 返回…

Linux系统之ARP命令的基本使用

Linux系统之ARP命令的基本使用 一、ARP介绍二、ARP命令帮助2.1 ARP的help帮助信息2.2 ARP命令的帮助解释 三、ARP命令的基本使用3.1 查看ARP缓存3.2 显示详细信息3.3 添加静态arp映射3.4 删除指定主机的ARP条目3.5 从文件读取并添加条目3.6 清除ARP缓存 四、注意事项五、总结 一…

wins系统资源监视器任务管理器运行监控CPU、内存、磁盘、网络运行状态

目录 1.Windows系统资源监视器的详细介绍2.通过任务管理器打开资源监视器3.任务管理中总体观察观察cpu、pid、应用程序、I/O次数或者说读写字节数 4.观察CPU观察cpu核心数&#xff0c;以及哪些占用cpu频率过高 5.观察内存观察各个应用占用的内存大小和对应线程 6.观察磁盘活动观…

【前端技巧】css篇

利用counter实现计数器 counter-reset&#xff1a;为计数器设置名称&#xff0c;语法如下&#xff1a; counter-rese: <idntifier><integer>第一个参数为变量名称&#xff0c;第二个参数为初始值&#xff0c;默认为0 counter-increment&#xff1a;设置计数器增…

LabVIEW与3D相机开发高精度表面检测系统

使用LabVIEW与3D相机开发一个高精度表面检测系统。该系统能够实时获取三维图像&#xff0c;进行精细的表面分析&#xff0c;广泛应用于工业质量控制、自动化检测和科学研究等领域。通过真实案例&#xff0c;展示开发过程中的关键步骤、挑战及解决方案&#xff0c;确保系统的高性…

宕机了, redis如何保证数据不丢?

前言 如果有人问你&#xff1a;"你会把 Redis 用在什么业务场景下&#xff1f;" 我想你大概率会说&#xff1a;"我会把它当作缓存使用&#xff0c;因为它把后端数据库中的数据存储在内存中&#xff0c;然后直接从内存中读取数据&#xff0c;响应速度会非常快。…

【Linux从入门到放弃】进程地址空间

&#x1f9d1;‍&#x1f4bb;作者&#xff1a; 情话0.0 &#x1f4dd;专栏&#xff1a;《Linux从入门到放弃》 &#x1f466;个人简介&#xff1a;一名双非编程菜鸟&#xff0c;在这里分享自己的编程学习笔记&#xff0c;欢迎大家的指正与点赞&#xff0c;谢谢&#xff01; 进…

如何更换OpenHarmony SDK API 10

OpenHarmony社区已经发布OpenHarmony SDK API 10 beta版本&#xff0c;有些 Sample案例 也有需要API10。那么如何替换使用新的OpenHarmony SDK API 10呢&#xff1f;本文做个记录。 1、如何获取OpenHarmony SDK 1.1 每日构建流水线 可以从OpenHarmony每日构建站点获取最新的…

【网络安全的神秘世界】已解决Failed to start proxy service on 127.0.0.1:8080

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 解决burpsuite无法在 127.0.0.1&#xff1a;8080 上启动代理服务端口被占用以及抓不到本地包的问题 Burpsuite无法启动proxy…

定个小目标之刷LeetCode热题(25)

这道题采用的解法是桶排序&#xff0c;画草图如下 代码如下 //基于桶排序求解「前 K 个高频元素」 class Solution {public int[] topKFrequent(int[] nums, int k) {HashMap<Integer, Integer> map new HashMap();for (int num : nums) {if (map.containsKey(num)) {m…

【安防天下】模拟视频监控系统——模拟监控系统的构成视频采集设备

文章目录 1 模拟监控系统的构成2 视频采集设备2.1 摄像机相关技术2.1.1 摄像机的工作原理2.1.2 摄像机的分类2.1.3 摄像机的主要参数 2.2 镜头相关介绍2.2.1 镜头的主要分类2.2.2 镜头的主要参数 1 模拟监控系统的构成 模拟视频监控系统又称闭路电视监控系统&#xff0c; 一般…

htb_Blurry

端口扫描 80 按照教程注册安装clear ml 加载configuration的时候会报错 将json里的API&#xff0c;File Store的host都添加到/etc/hosts中 即可成功初始化 查找clear ml漏洞 发现一个cve-2024-24590 下面是一个利用脚本&#xff0c;但不能直接用 ClearML-vulnerability-…

好用的linux一键换源脚本

最近发现一个好用的linux一键换源脚本&#xff0c;记录一下 官方链接 大陆使用 bash <(curl -sSL https://linuxmirrors.cn/main.sh)# github地址 bash <(curl -sSL https://raw.githubusercontent.com/SuperManito/LinuxMirrors/main/ChangeMirrors.sh) # gitee地址 …

Linux基础命令大全(详解版)

Linux基础命令&#xff08;详解版&#xff09; 文章目录 Linux基础命令&#xff08;详解版&#xff09;1.Linux的目录结构**2.Linux路径的描述方式**3.Linux命令基础格式4.ls命令 隐藏文件、文件夹5.pwd命令6.cd命令 特殊路径符7.mkdir命令 文件操作命令8.touch命令9.cat命令10…

英伟达中国特供芯片降价背后:巨头与市场的较量

英伟达&#xff0c;这家曾经在人工智能芯片领域独领风骚的巨头&#xff0c;近期在中国市场遭遇了一些挑战。为了应对来自华为等中国本土企业的竞争&#xff0c;英伟达不得不采取降价策略&#xff0c;调整其专为中国市场打造的H20芯片价格&#xff0c;甚至低于华为的同类产品。这…

S级猫主食冻干测评出来了:希喂、K9、朗诺实测分享

对于许多宠物主人来说&#xff0c;一到挑选主食冻干就头疼。尽管主食冻干为猫咪带来的益处远超过普通猫粮&#xff0c;但其价格也相对较高。因此&#xff0c;许多宠物主人担心高价购买的主食冻干营养价值并不高。实际上&#xff0c;除了营养&#xff0c;安全性和配方也是选购时…

【K8s】专题五(5):Kubernetes 配置之热更新工具 Reloader

以下内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01;如果对您有帮助&#xff0c;烦请点赞、关注、转发&#xff01;欢迎扫码关注个人公众号&#xff01; 目录 一、基本介绍 二、工作原理 三、部署方法 四、使用方法 一、基本介绍 Reloader 是一个用…

clickhouse学习笔记(四)库、表、分区相关DDL操作

目录 一、数据库操作 1、创建数据库 2、查询及选择数据库 3、删除数据库 二、数据表操作 1、创建表 2、删除表 3、基本操作 ①追加新字段 ②修改字段类型或默认值 ③修改字段注释 ④删除已有字段 ⑤移动数据表&#xff08;重命名&#xff09; ⑥清空表 三、默认值…

双层循环和循环语句

echo 打印 echo -n 表示不换行输出 echo -e 表示输出转义字符 echo \b 相当于退格键&#xff08;backspace&#xff09; echo \n 换行&#xff0c;相当于回车 echo \f 换行&#xff0c;换行后的新行的开头连着上一行的行尾 echo \t 相当于tab健 &#xff08;…

华测监测预警系统2.2 UserEdit.aspx SQL注入致RCE漏洞复现(CVE-2023-5827)

0x01 产品简介 华测监测预警系统2.2是一套针对地质灾害监测预警的科学、完善平台,实现了地质灾害防治管理的科学化、信息化、标准化和可视化。该系统由上海华测导航技术有限公司开发,主要服务于山体滑坡、地裂缝等地质灾害的自动化预警。 0x02 漏洞概述 华测监测预警系统2…