记录--vue中封装一个右键菜单组件(复制粘贴即可使用)
创始人
2025-05-30 09:27:28

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

组件介绍

关于web端的右键功能常用的地方有表格的右键,或者tab标签的右键等,本文记录一下封装一个右键菜单组件的思路步骤代码。

程序员除了会用轮子,还要尝试去贴合自己公司业务场景造轮子。

组件效果图

我们先看一下右键组件的效果图

1111.gif

组件分析

1.封装组件第一步考虑dom结构

我们观察这个右键菜单,可以明白右键菜单就是一个ul标签包裹着很多li标签的弹出层组件,如下图:

 每一行都是一个li,每一行中包含图标行按钮名称文字,于是我们的dom结构可以这样写:

    复制数据

2.dom结构搞清楚了,接下来就是考虑右键菜单组件接收的参数

如何考虑菜单组件接收哪些参数呢?

主要是想组件中会使用到哪些变量。如下:

  • 右键菜单需要一个数组,数组中存放的是每个菜单项的数据(菜单项图标、菜单项按钮名字、当然还有一些其他的需要传递的参数,统一挂在一个变量身上,如params)
  • 其次右键菜单组件的触发时机是拥挤点击右键的时候,那我们就得知道,用户右键点击的位置x、y的距离,所以这里还需要参数position中的x和y去记录距离视口的clientX和clientY值,因为右键菜单的位置就以这个作基准
  • 同时,我们还需要知道用户点击的是哪个菜单项按钮,所以再加一个事件名参数进去

综上所述,我们可以设计右键点击时,要给右键菜单组件传递的参数信息如下:

this.rightclickInfo = {position: {x: event.clientX,y: event.clientY,},menulists: [{fnName: "copy", // 事件名字,组件届时可this.$emit(fnName)抛出事件params: xxx,  // 参数,组件届时可this.$emit(fnName,params)抛出事件,并携带参数icoName: "el-icon-document-copy", // 图标名btnName: "复制数据", // 菜单项按钮名// 这三项是发散,可往下看// divided: true, // 是否禁用// disabled: true, // 是否带分隔线// children: [], // 是否有子菜单(递龟)},{fnName: "look",params: { row, column, event },icoName: "el-icon-view",btnName: "查看行数据",},],};

注意,上述参数代码示例中,多了三个参数divided、disabled、children,实际上,参数的设计要结合业务场景,我司的需求没有右键菜单禁用项,也不用有分割线,以及没有右键菜单的子菜单,所以封装组件就暂时没有加上这三个参数。

组件化、模块化的同时,主要高内聚,一个组件满足业务需求,精简为主,不可无节制的死命封装,否则就变成了诗山代码了,当然大家也可以仿照真正右键菜单去加功能,比如右键菜单可以绑定快捷键、改成递归形式等更多功能...

所以组件props中接收参数可以写成:

props: {// 接收右键点击的信息rightclickInfo: {type: Object,default: () => {return {position: {// 右键点击的位置x: null,y: null,},menulists: [{fnName: "", // 点击菜单项的事件名params: {}, // 点击的参数icoName: "", // 图标名btnName: "", // 按钮名},],};},},},

3.实现右键打开菜单弹出层,左键点击一下菜单弹出层就关闭了

不难发现,只要一右键菜单就弹出,点一下菜单消失,这种不停的显示和消失,去不停的v-if就不合适了,所以这里可以从v-show的角度出发

  • 一开始让菜单层隐藏display:none,而后再设置成dispaly:block
  • 当右键点击时,右键点击的位置参数positionx和y的值就会发生变化
  • 我们可以watch监听这个变化,position的x、y值变了,说明右键点击了
  • 右键点击了,我们就可以让菜单弹出层出现
  • 同时,需要监听鼠标点击事件,当点击的是右键或者中间滚轮键时,不去隐藏面板,点击的是左键时,才去隐藏面板

通过上述五点,我们即做到了显示隐藏菜单面板了

4.监听右键位置变化,显示菜单项代码

这一块的思路请看代码中注释即可,如下:

.table-right-menu {dispaly:none; // 初始为隐藏,监听更改显示
}watch: {// 监听右键点击时点击位置的变化,只要变化了,就弹出右键菜单供用户点击操作"rightclickInfo.position"(val) {let x = val.x; // 获取x轴坐标let y = val.y; // 获取y轴坐标let innerWidth = window.innerWidth; // 获取页面可是区域宽度,即页面的宽度let innerHeight = window.innerHeight; // 获取可视区域高度,即页面的高度/*** 注意,这里要使用getElementsByClassName去选中对应dom,因为右键菜单组件可能被多处使用* classIndex标识就是去找到对应的那个右键菜单组件的,需要加的* */ let menu =document.getElementsByClassName("table-right-menu")[this.classIndex]; menu.style.display = "block"; // 由隐藏改为显示let menuHeight = this.rightclickInfo.menulists.length * 30; // 菜单容器高let menuWidth = 180; // 菜单容器宽// 菜单的位置计算(边界留点间隙空间)menu.style.top =(y + menuHeight > innerHeight ? innerHeight - menuHeight : y) + "px";menu.style.left =(x + menuWidth > innerWidth ? innerWidth - menuWidth : x) + "px";// 因为菜单还要关闭,就绑定一个鼠标点击事件,通过e.button判断点击的是否是左键,左键关闭菜单document.addEventListener("mouseup", this.hide, false);},},hide(e) {if (e.button === 0) {// 0是左键、1是滚轮按钮或中间按钮(若有)、2鼠标右键let menu = document.querySelector(".table-right-menu");menu.style.display = "none"; // 菜单关闭document.removeEventListener("mouseup", this.hide); // 及时解绑监听事件}
},

事件绑定后别忘了解绑 document.removeEventListener("mouseup", this.hide);

5.知识点回顾e.button

  • e.button,鼠标事件
  • 返回一个数字,表示触发鼠标事件的是按下了哪个按钮
  • 值为只读,不可修改

具体返回数字值,表示鼠标事件发生时按下的鼠标按钮。

可能的值:

0:鼠标左键、 1:滚轮按钮或中间按钮(如果有)、 2:鼠标右键

IE8返回有一些不同:1:鼠标左键、 2:鼠标右键、 4:滚轮按钮或中间按钮(如果有)

注意:左手鼠标,返回值相反

6.组件中的事件要抛出去哦

item即为循环的菜单项,包含事件名、参数、图标名、按钮名

fnHandler(item) {this.$emit(item.fnName, item.params);// 事件再传出去,即为:// this.$emit('事件名',事件参数)
},

7.外界接收事件,正常@xxx='xxx'使用即可

如下:


使用组件

搭配el-table使用

  • el-table中可以使用封装好的事件:@row-contextmenu="xxx"

  • 然后在xxx方法中去传递参数给右键菜单组件即可,如下简化代码:

...
rightclickInfo:{}// 饿了么UI封装好的右键菜单事件,可直接使用,有行数据,列数据,以及事件
rightclick(row, column, event) {this.rightclickInfo = {position: {x: event.clientX,y: event.clientY,},menulists: [{fnName: "copy",params: { row, column, event },icoName: "el-icon-document-copy",btnName: "复制数据",},],};event.preventDefault(); // 阻止默认的鼠标右击事件
},

event.preventDefault()要加上,阻止默认的右键菜单事件

搭配普通dom使用

也同理,传参的时,需要阻止默认时间,如下:


区域内右键
onContextmen(){// 定义参数传递给my-right-menu组件 }

完整代码

复制粘贴即可使用哦

使用组件代码


封装组件代码


本文转载于:

https://juejin.cn/post/7174420692954251272

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

相关内容

热门资讯

53-exec进程替换 exec进程替换 一.exec系列 1.execl #include#include#include...
CF1737E Ela Goe... CF1737E Ela Goes Hiking 题目大意 nnn 只蚂蚁站成一排,第 ...
福州一日游哪里好玩,福州一日游... 福州一日游哪里好玩目录福州一日游哪里好玩福州一日游必去景点福州一天游,求推荐去哪福州一日游,有什么好...
新车5到6万买什么车好,预算5... 新车5到6万买什么车好目录新车5到6万买什么车好预算5万,有哪些车款可以推荐?买车5-6万买什么车好...
网络语言JMS是什么意思(jm... 本篇文章极速百科给大家谈谈网络语言JMS是什么意思,以及jms是什么意思中文翻译对应的知识点,希望对...
苹果6id锁怎么强制解除,苹果... 苹果6id锁怎么强制解除目录苹果6id锁怎么强制解除苹果六忘记ID激活锁怎么办如何强制解除id锁的方...
机器人阻抗控制(二) #阻抗控制 #机器人控制 #动力学方程 《Cartesian Impedance Control o...
SkyWalking 日志收集 SkyWalking 日志收集一、需求二、步骤2.1 pom文件引入依赖2.2 logback-sp...
DETR网络模型构建 这篇文章主要为记录DETR模型的构建过程 首先明确DETR模型的搭建顺序:首先是bac...
算法强化每日一题--组队竞赛 大家好 先看看题目 链接:组队竞赛__牛客网 [编程题]组队竞赛 牛牛举办了一次编...
什么是人际交往,什么是人际交往... 什么是人际交往目录什么是人际交往什么是人际交往?影响人际交往的因素有哪些?什么是人际交往人际交往指的...
自考大专什么时候报名,自考大专... 自考大专什么时候报名目录自考大专什么时候报名自考大专怎么报名 报考时间在几月份?每年的什么时候报名自...
蚕的变化过程,蚕的一生经历了哪... 蚕的变化过程目录蚕的变化过程蚕的一生经历了哪几个阶段?咨询:蚕的演变过程?蚕的生长变化顺序是怎样的?...
汽车出现service是什么意... 汽车出现service是什么意思目录汽车出现service是什么意思车上的service是什么意思?...
arcpy基础篇(6)-制图脚... arcpy.mapping模块可以实现地图制图的自动化,它的具体功能包括管理地图文档、...
基于 Zynq 的振动台控制器... 3 振动台控制器架构设计与实现 如前所述,Zynq-7000 本身已经具有了独特的架...
为什么手机收不到验证码短信,为... 为什么收不到短信验证码 3. 曾经向运营商申请过屏蔽短信号码,或添加过黑名单。 4. 短...
中国移动如何免费领取10G流量... 中国移动如何免费领取10G流量目录中国移动如何免费领取10G流量免费领10g流量的软件中国移动送10...
描写孩子童真的句子,孩子童真的... 描写孩子童真的句子目录描写孩子童真的句子孩子童真的唯美句子有哪些?描写童真童趣的一段话,急急!!!描...
QQ空间如何自定义封面,进入q... QQ空间如何自定义封面目录QQ空间如何自定义封面进入qq空间时的封面怎么设置?不花钱的那种怎样制作Q...
55-kill命令及实现kil... kill命令及实现kill命令 一. kill命令简介 在Linux系统中,kill命...
【问题与方法】如何使用vsco... 码字不易,如果各位看官感觉该文章对你有所帮助,麻烦点个关注,...
OMM导致tomcat引用假死 背景 在开发测试环境发现一个奇怪的情况,因查询100w条数据导致OOM,...
座落是哪个坐,座落是座还是坐?... 座落是哪个坐目录座落是哪个坐座落是座还是坐?座位是广字框的左还是哪个座?座落的意思座落是哪个坐 ...
人在什么情况下会失温(人体失温... 今天给各位分享人在什么情况下会失温的知识,其中也会对人体失温如何自救进行解释,如果能碰巧解决你现在面...
如何抓好安全生产工作 极速百科... 如何抓好安全生产工作目录如何抓好安全生产工作如何抓好安全生产工作我们应当如何做好安全生产工作,预防事...
小说阅读网作家中心(小说阅读网... 本篇文章极速百科给大家谈谈小说阅读网作家中心,以及小说阅读网作家中心作家登陆对应的知识点,希望对各位...
自定义变量名称和变量的生命周期 自定义变量名给已有变量改名#define A B 把A定义为B的别名例#define 整型 int整...
EC20免驱版 TX2无法使用 打开串口助手在root权限下busybox microom /dev/ttyUSB12发送指令(这...
不要迷信 QUIC 很多人都在强调 QUIC 能解决 HoL blocking 问题,不好意思࿰...