本文来自于 神奇的程序员

前言

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

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

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

实现思路

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

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

  • 布局右键菜单,编写样式

  • 将右键菜单需要的用到的数据在vuex中进行定义

  • 全局注册一个指令,命名为rightClick

  • 拦截被绑定元素的oncontextmenu事件,对组件传过来的值进行处理

  • 更新vuex里的右键菜单数据,触发右键菜单显示

实现过程

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

布局右键样式

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

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

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

        <divid="rightMenuDom"class="right-menu":style="{        display: rightMenuStatus,        top: rightMenuTop,        left: rightMenuLeft      }"    >      <ul>

        <li>          <spanv-for="item in rightMenuList":key="item.id"v-show="item.id <= 3"            @click="item.handler"            >{{ item.text }}          span>        li>        <li>          <spanv-for="item in rightMenuList":key="item.id"v-show="item.id > 3"            @click="item.handler"            >{{ item.text }}          span>        li>      ul>    div>  div>

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

  mounted() {    // 监听全局点击事件    document.addEventListener("click", () => {      // 隐藏右键菜单      this.$store.commit("updateRightMenuStatus", {        status: "none",        left: "0px",        top: "0px"      });    });  }

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

  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样式。

// 右键菜单样式  .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组件需要的文本数据和与之对应的事件处理函数
rightMenu: {  status: "none",  top: "0px",  left: "0px",  list: []}

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

// 更新右键菜单数据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里包含了指令传过来的参数
app.directive("rightClick", (el, binding) => {

});

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

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

  • 将事件对象放进一个数组中
  • 将每一个右键菜单的文本数据和与之对应的时间处理函数放进json数组中
  • 获取鼠标点击的位置,使用commit更新Vuex中的相关数据,渲染页面
  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       // 右键菜单对象, 添加名称      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,如下所示:

<liclass="row-panel"v-right-click="rightMenuObj">li>

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

// 右键菜单对象,菜单内容和处理事件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

写在最后

  • 公众号无法外链,如果文中有链接,可点击下方阅读原文查看?

● 【尤大出品】面向未来的前端构建工具 - Vite

● 一杯茶的时间,上手 Koa2 + MySQL 开发

● 动手实现一个 Koa 框架(万字实战好文)

·END·

图雀社区

汇聚精彩的免费实战教程

关注公众号回复 z 拉学习交流群

喜欢本文,点个“在看”告诉我

pyqt5 treeview鼠标右键菜单事件_【动手实践】使用 Vue 自定义指令实现右键菜单...相关推荐

  1. vue鼠标右键自定义菜单_使用Vue自定义指令实现右键菜单

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

  2. clientsideevents能定义几个click事件_分享8个非常实用的Vue自定义指令

    作者:lzg9527 https://juejin.cn/post/6906028995133833230 在 Vue,除了核心功能默认内置的指令 ( v-model 和 v-show ),Vue 也 ...

  3. vuejs 指令封装 button 加载效果_这些Vue自定义指令,让你的项目开发爽到爆

    受 AngularJS 的启发,Vue 内置了一些非常有用的指令(比如v-html 和 v-once等),每个指令都有自身的用途.完整的指令列表可以在这里查看. 这还没完,更棒的是可以开发自定义指令. ...

  4. vue 自定义指令弹窗鼠标拖拽弹窗表头,弹窗移动

    拖拽整个过程由三个事件完成 鼠标按下事件 onmousedown 鼠标移动事件 onmousemove 鼠标抬起事件 onmouseup Vue.directive('drag', {inserted ...

  5. vue 图片拖动加载 类似于地图_前端性能优化之图片懒加载(附vue自定义指令)...

    作者:lzg9527 链接:https://juejin.cn/post/6903774214780616718 在类电商类项目,往往存在大量的图片,如 banner 广告图,菜单导航图,美团等商家列 ...

  6. Vue 自定义指令上报 Google Analytics 事件统计

    发现问题 一般前端开发离不开数据统计,我们经常需要接入统计服务以方便运营,例如现在需要统计一个按钮 <template><button @click="handleClic ...

  7. 5e怎么绑定一键跳投_一个 Vue 自定义指令实现一键 Copy的功能

    话不多说先看效果,这个效果是用在真实项目中的实际效果哈: 指令是啥? 按照惯例,先请出官方的解释: 指令 (Directives) 是带有 v- 前缀的特殊特性.指令特性的值预期是单个 JavaScr ...

  8. vue自定义指令---处理加载图片失败时出现的碎图,onerror事件

    目录 一.自定义指令 1.局部注册和使用 2.全局注册和使用 二.自定义指令处理图片加载失败(碎图) 一.自定义指令 vue中除v-model.v-show等内置指令之外,还允许注册自定义指令,获取D ...

  9. python中下拉菜单大小_请问各位大神如何将下拉菜单的文字设定成一个值?

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 from tkinter import * from tkinter.ttk import Combobox class Calculator: def ...

最新文章

  1. [Machine Learning]--知识点疑问汇总[持续更新中]
  2. 计算机专业英语教程2.1.1,计算机专业英语教程目录
  3. 关于购买企业邮箱,谨防陷入几大误区
  4. 【深圳】掌通宝科技有限公司技术总监(兼架构师),约吗
  5. [vue] v-once的使用场景有哪些?
  6. 关于区块链,程序员需要了解什么
  7. Android睡眠唤醒机制--Kernel态
  8. oc语言学习之基础知识点介绍(三):类方法、封装以及继承的介绍
  9. 计算机vfp实验小结,vfp实验1报告心得体会
  10. 电子基础知识:常用电子元器件和基本工具
  11. 二进制像素绘制程序 scratch编程三级
  12. 论文翻译(上):Deep Learning Based Semantic Labelling of 3D Point Cloud in Visual SLAM
  13. Solr实现全文检索
  14. 你还在以为打马赛克就安全了吗?AI消除马赛克,GitHub开源项目上线三天收获近7000星
  15. 网卡驱动修改服务器,网卡驱动配置
  16. 字体设计中什么是断笔设计啊
  17. CSS简介代码实现表格(table)只有横线没有竖线的效果,一个简约卡片化精美的数据表格(类似Bootstrap表格)
  18. Linux上怎样安装gcc
  19. backupPC安装与使用
  20. springmvc 使用InternalResourceViewResolver解析URL文件

热门文章

  1. 卡通形象医疗病毒细菌宣传海报模板,psd分层,方便应用!
  2. 品质LOGO模板素材|想知道平面设计师如何设计徽标的秘密吗?
  3. 计算机设计大赛二等奖,学部在第十一届中国大学生计算机设计大赛中喜获二等奖...
  4. linux mysql 主从数据库_【Linux】【MySQL】MySQL主从数据库
  5. python在法律中的应用_Python在共轭梯度法中的运用
  6. 版本为2.5的OpenMP规范中的编译制导指令汇总
  7. GTK实现文本翻页(dailyNote.c)
  8. 零基础学python语言_致初学者:零基础如何学好,Python这门编程语言?
  9. python基础函数式编程(十七)
  10. js触发button的点击事件