Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用Vue自定义指令实现右键菜单

使用Vue自定义指令实现右键菜单

作者头像
神奇的程序员
发布于 2022-04-10 01:29:01
发布于 2022-04-10 01:29:01
1.9K20
代码可运行
举报
运行总次数:0
代码可运行

前言

浏览器里右键时会有一个默认的菜单,在我的开源项目中正好有自定义右键菜单的需求,在npm库找了下与之相关的包,发现都是以组件形式实现的,感觉那种做法太过繁琐。

于是,我就想着能不能像vue的内置指令那样,绑定到元素上,在这个元素上右键就能出现右键菜单,这样做就方便很多了。

看了下vue的自定义指令文档后,经过一番折腾,终于实现我的这个想法,本文就跟大家分享下我的实现思路以及过程,欢迎各位感兴趣的开发者阅读本文。

实现思路

Vue中有很多内置指令,例如:v-ifv-forv-model,它除了这些内置指令外,还允许我们开发者自己注册指令,来实现我们想实现的效果,对Vue自定义指令不熟悉的开发者可以先看一下文档:自定义指令。

接下来,就跟大家讲一下我的实现思路:

  • 布局右键菜单,编写样式
  • 将右键菜单需要的用到的数据在vuex中进行定义
  • 全局注册一个指令,命名为rightClick
  • 拦截被绑定元素的oncontextmenu事件,对组件传过来的值进行处理
  • 更新vuex里的右键菜单数据,触发右键菜单显示

实现过程

接下来,就跟大家分享下我的实现过程。

布局右键样式

我们先来看看这个组件需要哪些数据才能让其显示在鼠标所点的位置。

  • 它的显隐状态,即:元素css的display属性
  • 它的位置,即:元素css的lefttop属性
  • 它的文本数据,即:右键菜单要展示的内容,通过v-for来渲染
  • 它的事件处理函数,即:右键菜单中选项点击时,要进行的事件处理

我们在项目中找一个公用组件,确保这个组件会被渲染,在组件的template中加入下述代码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!--右键菜单-->
    <div
      id="rightMenuDom"
      class="right-menu"
      :style="{
        display: rightMenuStatus,
        top: rightMenuTop,
        left: rightMenuLeft
      }"
    >
      <ul>
        <!--分为2组渲染-->
        <li>
          <span
            v-for="item in rightMenuList"
            :key="item.id"
            v-show="item.id <= 3"
            @click="item.handler"
            >{{ item.text }}
          </span>
        </li>
        <li>
          <span
            v-for="item in rightMenuList"
            :key="item.id"
            v-show="item.id > 3"
            @click="item.handler"
            >{{ item.text }}
          </span>
        </li>
      </ul>
    </div>
  </div>

随后,在组件的mounted生命周期中添加全局点击事件的监听,目的是在点击任意位置后隐藏右键菜单。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  mounted() {
    // 监听全局点击事件
    document.addEventListener("click", () => {
      // 隐藏右键菜单
      this.$store.commit("updateRightMenuStatus", {
        status: "none",
        left: "0px",
        top: "0px"
      });
    });
  }

紧接着,在组件的computed中获取Vuex中定义的数据,用于渲染右键菜单。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  computed: {
    // 右键菜单显隐状态
    rightMenuStatus(): string {
      return this.$store.state.rightMenu.status;
    },
    // 右键菜单距离浏览器顶部高度
    rightMenuTop(): string {
      return this.$store.state.rightMenu.top;
    },
    // 右键菜单距离浏览器左边长度
    rightMenuLeft(): string {
      return this.$store.state.rightMenu.left;
    },
    // 右键菜单列表内容
    rightMenuList(): [] {
      return this.$store.state.rightMenu.list;
    }
  }

最后,给它编写css样式。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 右键菜单样式
  .right-menu {
    position: fixed;
    left: 0;
    top: 0;
    width: 166px;
    height: auto;
    background-color: rgb(242, 242, 242);
    border: solid 1px #C2C1C2;
    box-shadow: 0 10px 10px #C2C1C2;
    display: none;
    border-radius: 5px;

    ul {
      padding: 0;
      margin: 0;
      font-size: 15px;

      li {
        list-style: none;
        box-sizing: border-box;
        padding: 6px 0;
        border-bottom: 1px solid rgb(216, 216, 217);

        &:nth-child(1) {
          padding-top: 2px;
        }

        &:nth-last-child(1) {
          border-bottom: none;
        }

        span {
          display: block;
          height: 20px;
          line-height: 20px;
          padding-left: 16px;

          &:hover {
            background-color: #0070F5;
            cursor: pointer;
            color: #FFFFFF;
          }
        }
      }
    }
  }

在Vuex中定义数据

在vuex的配置文件中,找到state属性,添加下述代码。

  • status组件的显隐状态
  • top组件距离浏览器可视区域顶部的距离
  • left距离浏览器可视区域左边的距离
  • list组件需要的文本数据和与之对应的事件处理函数
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
rightMenu: {
  status: "none",
  top: "0px",
  left: "0px",
  list: []
}

随后在mutations中添加更新数据的方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 更新右键菜单数据
updateRightMenuStatus(state, menuObj: rightMenuAttribute) {
  state.rightMenu.status = menuObj.status;
  state.rightMenu.top = menuObj.top;
  state.rightMenu.left = menuObj.left;
  state.rightMenu.list = menuObj.list;
}

注册全局指令

我们在vue的入口文件:main.ts中,注册一个全局指令rightClick

  • el为我们绑定指令的元素
  • binding里包含了指令传过来的参数
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
app.directive("rightClick", (el, binding) => {
  
});

拦截右键事件处理指令参数

上面我们注册了一个全局指令,我们需要在它的函数内部为指令所绑定的元素重写其点击事件,处理指令传过来的参数。

  • 将事件对象放进一个数组中
  • 将每一个右键菜单的文本数据和与之对应的时间处理函数放进json数组中
  • 获取鼠标点击的位置,使用commit更新Vuex中的相关数据,渲染页面
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  el.oncontextmenu = function(e: MouseEvent) {
    const textArray = binding.value.text;
    const handlerObj = binding.value.handler;
    // 事件处理数组
    const handlerArray = [];
    // 处理好的右键菜单
    const menuList = [];
    // 将事件处理函数放入数组中
    for (const key in handlerObj) {
      handlerArray.push(handlerObj[key]);
    }
    // 追加右键菜单数据
    for (let i = 0; i < textArray.length; i++) {
      // 右键菜单对象, 添加名称
      const menuObj = {
        text: textArray[i],
        handler: handlerArray[i],
        id: i + 1
      };
      menuList.push(menuObj);
    }
    // 鼠标点的坐标
    const oX = e.clientX;
    const oY = e.clientY;
    // 右键菜单出现后的位置
    store.commit("updateRightMenuStatus", {
      status: "block",
      left: oX + "px",
      top: oY + "px",
      list: menuList
    });
    return false;
  };

在组件中使用指令

完成上述操作后,我们就已经实现了右键自定义菜单的指令,接下来,我们来看看如何在组件中使用我们注册的指令。

在你想要绑定右键菜单的html元素上添加v-right-click,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<li
  class="row-panel"
  v-right-click="rightMenuObj"
>
</li>

在组件的data中定义右键菜单需要的数据,即上面代码中声名的rightMenuObj

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 右键菜单对象,菜单内容和处理事件
rightMenuObj: {
  text: [
    "查看资料",
    "复制用户id",
    "移除该会话",
    "在联系人中查看",
    "在单聊窗口中打开",
    "会话置顶"
  ],
  handler: {
    checkingData() {
      console.log("查看资料点击事件");
    },
    copyId() {
      console.log("复制用户id点击事件");
    },
    removeItem() {
      console.log("移除会话点击事件");
    },
    showContact() {
      console.log("在联系人中查看");
    },
    showSingleChat() {
      console.log("在单聊窗口中打开");
    },
    topConversation() {
      console.log("会话置顶");
    }
  }
}

随后,我们就可以运行看效果了,如下所示,已经成功实现了我们想要的效果。

图片过大,微信无法加载,可点击下方阅读原文进行查看。

代码地址

本文中演示所用的组件GitHub地址如下:

msg-list.vue

main.ts

main-content.vue

main-content.scss

index.ts

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 神奇的程序员 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
2 条评论
热度
最新
请问你的github具体地址是什么?
请问你的github具体地址是什么?
11点赞举报
https://github.com/likaia/
https://github.com/likaia/
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
美团前端vue面试题_2023-05-19
Vue3最重要更新之一就是Composition API,它具有一些列优点,其中不少是针对Options API暴露的一些问题量身打造。是Vue3推荐的写法,因此掌握好Composition API应用对掌握好Vue3至关重要
用户10358241
2023/05/19
1.1K0
Vue3.0实现原生高度可自定义菜单组件vue3-menus
Vue3.0 原生实现完全自定义右键菜单组件, 零依赖,可根据可视区域自动调节显示位置,可支持插槽完全重写每一项菜单
用户6682160
2021/08/29
2.4K0
Vue3.0实现原生高度可自定义菜单组件vue3-menus
使用vue封装右键菜单插件
上周跟大家分享了如何使用vue的自定义指令实现自定义浏览器右键菜单,大家都觉得挺有意思的,这次我把它做成了插件,上传到了npm仓库。
神奇的程序员
2022/04/10
2.9K0
JavaScript 自定义html元素鼠标右键菜单
在触发contextmenu事件时,取消默认行为(也就是阻止浏览器显示自带的菜单),获取右键事件对象,来确定鼠标的点击位置,作为显示菜单的left和top值
授客
2019/12/10
2.6K0
JavaScript 自定义html元素鼠标右键菜单
Element Tabs 标签页实现右键自定义菜单
如果tab标签页比较多的话,一个个关闭比较麻烦,可以右键显示菜单,关闭所有的标签页或者特定的标签页
tianyawhl
2020/04/13
4.1K0
vue2.0和better-scroll实现左右联动效果
在做移动端商城或者其他页面的时候,经常会遇到左右联动的效果,今天小编vue2.0和better-scroll这个插件一起实现左右联动效果。
小周sir
2019/09/23
1.4K0
vue2.0和better-scroll实现左右联动效果
Vue2.0 Vuex初始化及歌手数据的配置
本次的系列博文的知识点讲解和代码,主要是来自于Vue 2.0 高级实战-开发移动端音乐WebApp课程,由个人总结并编写,其代码及知识点部分,均有所更改和删减,关于更多 Vue 2.0 的知识和实际应用,还请大家购买课程进行学习实践,该系列博文的发布已得到黄轶老师的授权许可
Nian糕
2018/08/21
7740
Vue2.0 Vuex初始化及歌手数据的配置
前端成神之路-Vuex
Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享
海仔
2021/05/06
1.5K0
Vue折腾记 - (1)写一个不大靠谱的二级侧边栏
前言 本来想写个新手系列教程..发现这种东西一搜索一大把; 那就写点实战类的吧;这篇文章你能学点什么? 当然是一些常见内置指令的用法,组件过渡,遍历的思路等等 效果图 实现思路 过渡用css - 遍
CRPER
2018/08/28
4880
Vue折腾记 - (1)写一个不大靠谱的二级侧边栏
JS自定义右键菜单—复制到粘贴板(jQuery和原生JS实现)
自定义右键菜单——复制到粘贴板 需求: 鼠标在li标签上点击右键出现菜单,主要是复制等功能 屏蔽浏览器默认右键点击事件 右键菜单出现在鼠标点击的位置 点击屏幕其他位置菜单消失 点击之后有回调 实现: 1、使用jQuery - 右键菜单插件contextMenu 在项目中引入jquery.contextMenu.js 和 jquery.contextMenu.css, 同时 contextMenu 依赖 jQuery。 初始化插件 $.contextMenu({ selector: 'li',
从入门到进错门
2018/08/21
5.2K0
JS自定义右键菜单—复制到粘贴板(jQuery和原生JS实现)
Fluid -39- 自定义右键菜单
博客的右键菜单,本质上很简单,就是在当前 Html 界面劫持右键单击事件,禁止默认右键弹出,把自己的右键菜单在当前鼠标位置展示出来。
为为为什么
2024/01/25
2290
Fluid -39- 自定义右键菜单
vue实战电商管理后台
这里我们使用了 ElementUI 组件 el-container、el-menu
Remember_Ray
2020/10/09
4.6K3
vue实战电商管理后台
自定义下拉菜单封装
前段时间面试的时候,面试官看了我简历上一句“擅长组件封装”,就丢给我一个挑战:“那你来做一个可搜索、支持多选的下拉菜单组件吧,最好能加上键盘操作。”这个题目一下子点燃了我——它看起来简单,却能充分暴露一个人对事件控制、状态管理、DOM 操作乃至交互体验的理解。
繁依Fanyi
2025/05/07
1870
巧妙实现右键菜单功能,提升用户操作体验
今日推荐:Spring AI再更新:如何借助全局参数实现智能数据库操作与个性化待办管理
繁依Fanyi
2024/11/22
1610
VUE实现一个购物车
想象每个组件都分别为家中的成员:爸爸、妈妈、孩子们。但是,作为一个家庭,他们需要共享状态。在这个家庭中,充当看家狗的Vuex就是来帮助我们解决问题的。
HelloWorldZ
2024/03/20
2200
VUE实现一个购物车
分享8个非常实用的Vue自定义指令
链接:https://segmentfault.com/a/1190000038475001
coder_koala
2021/01/06
1.6K0
【可视化】Vue基础
Vue框架,框架的作者,尤雨溪,组件化,快速开发的特点。 生命周期 beforeCreate:组件刚刚被创建 created:组件创建完成 生成
达达前端
2019/12/20
6150
【可视化】Vue基础
深入Vue.js:从基础到进阶的全面学习指南
Vue.js是一个用于构建用户界面的渐进式JavaScript框架。与其他重量级框架不同,Vue.js采用自底向上增量开发的设计。Vue.js的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。在现代前端开发中,Vue.js与React、Angular并列,成为三大主流框架之一。
九转成圣
2024/06/08
3630
Fabric.js 右键菜单
Fabric.js 默认**没提供 鼠标右键事件**,只有 鼠标按键点击 、鼠标按键抬起 、鼠标移动 等事件。 但在工作中有可能需要用到 “右键” 事件,比如 “右键菜单” 。所以就有了本文。 本文主要关注 Fabric.js 的主要 api 有:
德育处主任
2022/04/17
7.8K0
Fabric.js 右键菜单
VUE2全家桶精讲
概念:Vue (读音 /vjuː/,类似于 view) 是一套构建用户界面的渐进式框架。
HelloWorldZ
2024/03/20
5540
VUE2全家桶精讲
相关推荐
美团前端vue面试题_2023-05-19
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验