主要思路:利用 @contextmenu事件,然后固定定位右键菜单位置

<template>
  <div class="page">
    <!-- @contextmenu鼠标右键显示菜单事件 -->
    <!-- 给vue组件绑定事件时候,组件加上.native才能监听原生事件,否则会认为监听的是来自Item组件自定义的事件, -->
    <!-- .prevent用来阻止浏览器默认事件,因浏览器右键会显示自己设置好的菜单所以需要设置默认阻止事件 -->
    <el-button type="primary" @contextmenu.prevent.native="openMenu($event)"
      >右键显示菜单</el-button
    >
    <!-- 因右键自定义菜单事件需要获取当前点击的位置,所以此处绑定动态样式来控制菜单实时跟踪鼠标右键点击位置 -->
    <ul
      v-show="visible"
      :style="{ left: left + 'px', top: top + 'px' }"
      class="contextmenu"
    >
      <li>菜单一</li>
      <li>菜单二</li>
    </ul>
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {
      visible: false,
      top: 0,
      left: 0,
    };
  },
  watch: {
    //   监听属性对象,newValue为新的值,也就是改变后的值
    visible(newValue, oldValue) {
      if (newValue) {
        //菜单显示的时候
        // document.body.addEventListener,document.body.removeEventListener它们都接受3个参数
        // ("事件名" , "事件处理函数" , "布尔值");
        // 在body上添加事件处理程序
        document.body.addEventListener("click", this.closeMenu);
      } else {
        //菜单隐藏的时候
        // 移除body上添加的事件处理程序
        document.body.removeEventListener("click", this.closeMenu);
      }
    },
  },
  methods: {
    //右击
    openMenu(e) {
      var x = e.pageX; //这个应该是相对于整个浏览器页面的x坐标,左上角为坐标原点(0,0)
      var y = e.pageY; //这个应该是相对于整个浏览器页面的y坐标,左上角为坐标原点(0,0)
      this.top = y;
      this.left = x;
      this.visible = true; //显示菜单
    },
    //关闭菜单
    closeMenu() {
      this.visible = false; //关闭菜单
    },
  },
};
</script>

<style scoped>
.contextmenu {
  margin: 0;
  background: #fff;
  z-index: 3000;
  position: fixed; //关键样式设置固定定位
  list-style-type: none;
  padding: 5px 0;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 400;
  color: #333;
  box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
}

.contextmenu li {
  margin: 0;
  padding: 7px 16px;
  cursor: pointer;
}
.contextmenu li:hover {
  background: #eee;
}
</style>

演示效果:

Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐