不想要网页默认的右键菜单栏,怎么封装一个可以自定义的右键菜单组件?

说在前面

🎈网页的功能和用途可能各不相同,在传统右键菜单栏中无法满足每个用户的个性化需求。通过自定义右键菜单栏,用户可以根据自己的需求添加、调整和删除菜单选项,以实现个性化定制。通过自定义右键菜单栏,可以为用户提供快速访问常用功能和操作的便捷方式,从而提高用户体验。

效果展示

实现原理

1、oncontextmenu事件了解一下

oncontextmenu 事件在元素中用户右击鼠标时触发并打开上下文菜单。

oncontextmenu是一个DOM事件,它在用户右键点击时触发。可以通过在HTML元素上添加oncontextmenu属性来指定右键菜单的处理函数。

例如,在一个按钮元素上添加oncontextmenu属性:

<button oncontextmenu="showContextMenu(event)">右键点击我</button>

在这个示例中,当用户右键点击按钮时,会调用showContextMenu函数,并将事件对象作为参数传递给该函数。

在JavaScript代码中,可以定义showContextMenu函数来处理右键菜单的显示和操作:

function showContextMenu(event) {event.preventDefault(); // 阻止默认的右键菜单弹出// 显示自定义右键菜单// ...
}

在showContextMenu函数中,通过调用event.preventDefault()方法阻止浏览器默认的右键菜单弹出。然后,可以根据需要执行自定义的逻辑,例如显示自定义的右键菜单。

2、在指定容器元素自定义右键菜单

首先,使用getElementById方法获取绑定右键菜单的DOM元素和右键菜单的容器元素。如果获取失败,则直接返回。

const dom = document.getElementById(this.domId);
if (!dom) return;

接着,给绑定右键菜单的DOM元素添加oncontextmenu事件处理函数。当用户触发右键点击事件时,首先调用hideAllMenu方法隐藏所有的右键菜单,然后通过event.preventDefault方法禁止默认行为,防止浏览器弹出默认的右键菜单。接下来,计算出鼠标指针相对于文档顶部和左侧的位置,并设置右键菜单的位置和显示状态。

const that = this;
dom.oncontextmenu = function (e) {that.hideAllMenu(that.uid);// 自定义body元素的鼠标事件处理函数e = e || window.event;e.preventDefault();let scrollTop =document.documentElement.scrollTop ||document.body.scrollTop; // 获取垂直滚动条位置let scrollLeft =document.documentElement.scrollLeft ||document.body.scrollLeft; // 获取水平滚动条位置menu.style.display = "block";menu.style.left = e.clientX + scrollLeft + "px";menu.style.top = e.clientY + scrollTop + "px";
};

最后,给document对象添加onclick事件处理函数。当用户在其他位置点击鼠标时,调用hideAllMenu方法隐藏所有的右键菜单。

document.onclick = function () {that.hideAllMenu();
};
hideAllMenu(id) {const jMenu = document.getElementsByClassName("j-mouse-menu");for (let i = 0; i < jMenu.length; i++) {if (jMenu[i].id != id) jMenu[i].style.display = "none";}
},

3、封装成一个组件

(1)template菜单模板
<div :id="uid" class="j-mouse-menu"><slot name="header"></slot><ul><liv-for="menuItem in menu":key="menuItem.id"@click="menuClick(menuItem)">{{ menuItem.label }}</li></ul><slot name="body"></slot><slot name="footer"></slot>
</div>

使用:id="uid"绑定了组件的id属性,该属性值由组件实例的uid属性提供。这样可以确保每个组件实例都有唯一的id。

然后,给组件添加了j-mouse-menu类,用于设置组件的样式。

在组件的内容区域中,使用了Vue的插槽机制。

  • <slot name="header"></slot>定义了一个名为"header"的插槽,用于放置菜单栏的头部内容。
  • <ul>标签下使用了v-for指令遍历menu数组,生成菜单项。
  • 菜单项使用<li>标签表示,并通过:key绑定了唯一的menuItem.id作为key值。
  • 通过@click绑定了menuClick方法,该方法会在点击菜单项时被调用。
  • 菜单项的显示文本使用插值语法{{ menuItem.label }}来动态显示。

接下来,又定义了两个插槽:

  • <slot name="body"></slot>用于放置菜单栏的主体内容。
  • <slot name="footer"></slot>用于放置菜单栏的底部内容。
(2)props入参
props: {domId: {type: String,default: "",},menu: {type: Array,default: () => {return [];},},
},

domId表示需要绑定右键菜单的DOM元素容器的id,menu表示右键菜单的选项列表,menu数据格式如下:

[{id: "1",label: "菜单1"},{id: "2",label: "菜单2",click: this.test},{id: "3",label: "菜单3"},{id: "4",label: "菜单4"},{id: "5",label: "菜单5"}
]
(3)菜单点击回调
menuClick(item) {if (item.click) {item.click(item);return;}this.$emit("menuClick", item);
},

首先判断item对象是否存在click属性。如果存在,则执行item.click(item),并将item作为参数传递给click函数。然后,返回结束方法的执行。

如果item对象不存在click属性,即没有自定义的点击处理函数,那么就通过this.$emit(“menuClick”, item)语法触发一个名为"menuClick"的自定义事件,并将item作为参数传递给父组件。

(4)完整组件代码
<template><div><div :id="uid" class="j-mouse-menu"><slot name="header"></slot><ul><liv-for="menuItem in menu":key="menuItem.id"@click="menuClick(menuItem)">{{ menuItem.label }}</li></ul><slot name="body"></slot><slot name="footer"></slot></div></div>
</template><script>
import { getUId } from "../../../utils/strTool";
export default {name: "JMouseMenu",props: {domId: {type: String,default: "",},menu: {type: Array,default: () => {return [];},},},data() {return {uid: "",};},created() {this.setUid();},mounted() {this.init();},methods: {setUid() {this.uid = "j-mouse-menu-" + getUId();},init() {// 自定义鼠标右键菜单栏const dom = document.getElementById(this.domId);if (!dom) return;const menu = document.getElementById(this.uid);const that = this;dom.oncontextmenu = function (e) {that.hideAllMenu(that.uid);// 自定义body元素的鼠标事件处理函数e = e || window.event;e.preventDefault();let scrollTop =document.documentElement.scrollTop ||document.body.scrollTop; // 获取垂直滚动条位置let scrollLeft =document.documentElement.scrollLeft ||document.body.scrollLeft; // 获取水平滚动条位置menu.style.display = "block";menu.style.left = e.clientX + scrollLeft + "px";menu.style.top = e.clientY + scrollTop + "px";};// 鼠标点击其他位置时隐藏菜单document.onclick = function () {that.hideAllMenu();};},hideAllMenu(id) {const jMenu = document.getElementsByClassName("j-mouse-menu");for (let i = 0; i < jMenu.length; i++) {if (jMenu[i].id != id) jMenu[i].style.display = "none";}},menuClick(item) {if (item.click) {item.click(item);return;}this.$emit("menuClick", item);},},
};
</script><style lang="less" scoped>
.j-mouse-menu {display: none;position: absolute;min-width: 8em;max-width: 15em;border: 1px solid #ccc;background: #eee;ul {margin: 5px 0;padding: 0;}li {height: 30px;line-height: 30px;color: #21232e;font-size: 12px;text-align: center;cursor: default;padding: 0;margin: 0;list-style-type: none;border-bottom: 1px dashed #cecece;&:hover {background-color: #cccccc;}}
}
</style>
(5)组件使用
<j-mouse-menu:domId="'j-mouse-menu-view-content1'":menu="myMenu"@menuClick="menuClick"
><template v-slot:header><div class="menu-slot-header">🌝JYeontu</div></template><template v-slot:footer><div class="menu-slot">🦁🐼</div></template>
</j-mouse-menu>

通过插槽自定义右键菜单的头部和底部内容,菜单列表通过menu参数传入子组件,并绑定菜单点击事件menuClick

data(){return {myMenu: [{id: "1",label: "菜单1"},{id: "2",label: "菜单2",click: this.test},{id: "3",label: "菜单3"},{id: "4",label: "菜单4"},{id: "5",label: "菜单5"}]}
},
methods:{menuClick(menuItem) {alert("点击了:" + menuItem.label);},test(menuItem) {alert("test-" + menuItem.id);},alert(label) {alert("点击了:" + label);}
}

组件库

组件文档

目前该组件也已经收录到我的组件库,组件文档地址如下:
http://jyeontu.xyz/jvuewheel/#/JMouseMenu

组件内容

组件库中还有许多好玩有趣的组件,如:

  • 悬浮按钮
  • 评论组件
  • 词云
  • 瀑布流照片容器
  • 视频动态封面
  • 3D轮播图
  • web桌宠
  • 贡献度面板
  • 拖拽上传
  • 自动补全输入框
  • 图片滑块验证

等等……

组件库源码

组件库已开源到gitee,有兴趣的也可以到这里看看:https://gitee.com/zheng_yongtao/jyeontu-component-warehouse

觉得有帮助的可以点个star~

有什么问题或错误可以指出,欢迎pr~

有什么想要实现的组件或想法可以联系我~

公众号

关注公众号『前端也能这么有趣』,获取更多有趣内容。

发送『组件库』获取源码

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。

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

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

相关文章

Mapbox加载浙江省天地图服务和数据处理

1. 加载影像服务 通过浙江省天地图官网申请所需服务&#xff0c;使用token获取服务数据 由于浙江省天地图使用的坐标系是 cgcs2000&#xff0c;需要使用 的框架对应为 cgcs2000/mapbox-gl&#xff0c;通过cdn引入或npm下载 影像服务地址为&#xff1a; ‘https://ditu.zjzw…

Web安全漏洞专项靶场—SQL注入—docker环境—sqli-labs靶场—详细通关指南

SQL注入—sqli-labs靶场 零、前言一、环境搭建①、VirtualBox②、Kali Linux③、Docker 二、闯关开始1、Less-1——union2、Less-2—数字型—union3、Less-3—)—union4、Less-4—")—union5、Less-5——布尔盲注6、Less-6—"—布尔盲注7、Less-7—))7.1—布尔盲注7.…

Xcode查看APP文件目录

一、连接真机到MAC电脑上 二、打开Devices 点击window -> Devices and Simulatores 三、选中设备、选择app 四、选择下载内容 五、查看文件内容 得到的文件 右键显示包内容&#xff0c;获得APP内数据 六、分发证书无法下载 使用分发的证书无法下载文件内容&#xf…

x-cmd pkg | hurl - HTTP 请求处理工具

目录 简介首次用户功能特点竞品和相关作品进一步探索 简介 Hurl 是 HTTP 请求处理工具&#xff0c;支持使用简单的纯文本格式定义的 HTTP 请求。它的用途非常广泛&#xff0c;既可以用于获取数据&#xff0c;也可以用于测试HTTP会话。 它可以链式处理请求&#xff0c;捕获数值…

LeetCode 670 最大交换数

周一&#xff0c;非常冷&#xff0c;大风呼呼的&#xff0c;上班路都走不动。 好消息&#xff0c;马上要过年了。大风吹&#xff0c;天气好。 过年过年&#xff0c;回家过年~ 学生时代的迷茫是不应该存在的&#xff0c;最好的时光应该尽情享受&#xff0c;而不应该自己给加层…

GO 的那些 IDE

文章目录 支持哪些功能快捷键代码高亮代码格式化代码提示导航跳转代码调试构建编译其他功能 GO有哪些IDEGolandVS CodeVim GOSublime TextAtomLiteIDEEclipse 总结 “程序员为什么要使用 IDE”&#xff0c;在一些社区论坛&#xff0c;经常可以看到这样的提问。关于是否应该使用…

有效的括号

有效的括号 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/valid-parentheses/…

Go语言学习笔记:基础语法和类型

Go语言学习笔记&#xff1a;基础语法和类型 目录 Go语言学习笔记&#xff1a;基础语法和类型学习路线前言变量声明常量数据类型布尔型&#xff08;Boolean&#xff09;整型&#xff08;Integer&#xff09;浮点型&#xff08;Floating point&#xff09;复数型&#xff08;Comp…

LoadRunner从零开始之接触LoadRunner

LoadRunner 是Mercury Interactive 公司开发的一款成熟的性能测试工具&#xff0c;LoadRuner 作为性能测试的实现者&#xff0c;涉及了性能测试流程、性能测试技术和软件 体系架构等众多方面的知识点&#xff0c;可以说&#xff0c;学习LoadRuner 是理解和学习性能测试 的非常好…

elastic search入门

参考1&#xff1a;Elastic Search 入门 - 知乎 参考2&#xff1a;Ubuntu上安装ElasticSearch_ubuntu elasticsearch-CSDN博客 1、ElasticSearch安装 1.1安装JDK&#xff0c;省略&#xff0c;之前已安装过 1.2创建ES用户 创建用户&#xff1a;sudo useradd esuser 设置密码&…

大模型相关学习资料整理

1. 核心2框架 1. semantic-kernel【微软】 https://learn.microsoft.com/en-us/semantic-kernel/overview/ 2. LangChain https://www.langchain.asia/ https://python.langchain.com/docs/get_started/introduction 2. 技术点 1. Function Call https://platform.opena…

mac安装node多环境

安装node node安装包 查询node环境 一般都是最新稳定版本 切换node环境 一般有些项目需要老的node版本支持&#xff0c;但是新的项目老的版本又不支持&#xff0c;这个时候需要切换node版本来运行各个项目 这个时候需要一个npm包 n来管理这些node环境包 sudo npm i -g n注…

Linux与windows互相传输文件之rzsz命令

文章目录 关于rzsz安装软件使用命令方法一&#xff1a;直接拖拽方法二&#xff1a;直接在终端输入rz 关于rzsz 这个工具用于 windows 机器和远端的 Linux 机器通过 XShell 传输文件 安装完毕之后可以通过拖拽的方式将文件上传过去 首先看一下我们的机器可以使用网络吗&#xff…

导出 MySQL 数据库表结构、数据字典word设计文档

一、第一种 &#xff1a;利用sql语句查询 需要说明的是该方法应该适用很多工具&#xff0c;博主用的是navicat SELECT TABLE_NAME 表名,( i : i 1 ) AS 序号,COLUMN_NAME 列名, COLUMN_TYPE 数据类型, DATA_TYPE 字段类型, CHARACTER_MAXIMUM_LENGTH 长度, IS_NULLABLE…

linux性能优化-磁盘I_O优化

1.文件系统 1.1.文件系统的工作原理 文件系统是在磁盘的基础上&#xff0c;提供了一个用来管理文件的树状结构。 接下来我们就看看Linux 文件系统的工作原理。 1.1.1索引节点和目录项 在 Linux 中一切皆文件 ,文件系统,本身是对存储设备上的文件&#xff0c;进行组织管理的…

安裝火狐和穀歌流覽器插件FoxyProxy管理海外動態IP代理

代理生態系統擁有大量有用的實用程式&#xff0c;使海外代理IP代理設置的使用變得簡單起來。其中一種類型叫做代理管理工具&#xff0c;像FoxyProxy就是該工具集比較受歡迎的。 本文將全面解析FoxyProxy擴展的功能和特性、Foxyproxy怎麼下載、以及如何在穀歌流覽器和火狐流覽器…

[小程序]Http网络请求

一、数据请求限制 出于安全性(bushi)考虑&#xff0c;小程序请求的数据接口必须具备以下两个条件&#xff1a; ①只能请求Https类型 ②必须将接口域名添加到信任列表中 1.配置request合法域名 配置步骤如下&#xff1a;小程序管理后台->开发->开发设置->服务器域名-&g…

【GitHub项目推荐--12306 抢票助手 python】【转载】

这个项目名很干脆&#xff0c;不知道以为是 12306 网站的源码&#xff0c;其实不是这是全 GitHub最德高望重的抢票小助手&#xff0c;功能一直在更新&#xff0c;且现已支持 Python 3.6 以上版本。 开源地址&#xff1a;https://github.com/testerSunshine/12306

开源项目CuteSqlite开发笔记(八):Windows 64位/32位使用GetWindowLongPtr钩子函数

需求描述 在开发CuteSqlite的时候&#xff0c; 有一个功能需要实现&#xff0c;鼠标移到WTL::CStatic上后&#xff0c;发送消息通知CToolTipCtrl弹出。 遇到问题 WTL::CStatic控件没有相应 WM_MOUSEMOVE 消息&#xff0c;需要返回一个HTCLIENT消息来让窗口处理函数执行 WM_MO…

【征服redis16】收官-redis缓存一致性问题解决方案

今天我们来写redis最后一篇&#xff1a;redis作为缓存时如何与数据库实现数据一致的问题。 最近看redis看得有点麻了&#xff0c;这篇就简单描述吧 目录 1.什么是缓存与数据库一致性问题 1.1 缓存一致性的概念 1.2 缓存不一致的场景 2.缓存不一致的解决思路 1.什么是缓存…