Vue中 实现右键自定义菜单

勤奋不是嘴上说说而已,而是实际的行动,在勤奋的苦度中持之以恒,永不退却。业精于勤,荒于嬉;行成于思,毁于随。在人生的仕途上,我们毫不迟疑地选择勤奋,她是几乎于世界上一切成就的催产婆。只要我们拥着勤奋去思考,拥着勤奋的手去耕耘,用抱勤奋的心去对待工作,浪迹红尘而坚韧不拔,那么,我们的生命就会绽放火花,让人生的时光更加的闪亮而精彩。

导读:本篇文章讲解 Vue中 实现右键自定义菜单,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

1. 原生方法

1.1 完整代码

<template>
  <div class="home">
    <!-- 在需要右键菜单的元素,绑定contextmenu事件 -->
    <div 
    	class="test" v-for="item in menus" :key="item" 
    	@contextmenu.prevent="openMenu($event,item)">{{item}}</div>
    	
    <!-- 右键菜单部分 -->
    <ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
      <li @click="handleDelete">删除</li>
      <li @click="handleDownloadFile">下载</li>
      <li @click="handlePreviewFile">预览</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      menus:[1,2,3], // 模拟数据
      rightClickItem:'',
      visible: false, // 是否展示右键菜单
      top:0,
      left:0,
    };
  },
  methods: {
    // 打开右键菜单
    openMenu(e,item){
      this.visible = true;
      this.top = e.pageY;
      this.left = e.pageX;
      this.rightClickItem = item;
    },
    // 关闭右键菜单
    closeMenu(){
      this.visible = false;
    },
	
    handleDelete(){},
    handleDownloadFile(){},
    handlePreviewFile(){},
  },
  watch: {
    // 监听 visible,来触发关闭右键菜单,调用关闭菜单的方法
    visible(value) {
      if (value) {
        document.body.addEventListener('click', this.closeMenu)
      } else {
        document.body.removeEventListener('click', this.closeMenu)
      }
    }
  },
};
</script>

<style lang="stylus" scoped>
.home{
  display: flex;
  justify-content: space-around;
  width: 100%;
  height: 600px;
  .test{
    width: 80px;
    height: 60px;
    background-color pink;
    text-align:center;
    font-size:32px;  
    color: green;
  }
  .contextmenu {
    margin: 0;
    background: #fff;
    z-index: 3000;
    position: absolute;
    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>

1.2 效果
在这里插入图片描述

2. 使用插件 vue-context-menu

demo演示地址
GitHub地址
npm 地址

安装

npm install vue-contextmenu --save

引入

import VueContextMenu from 'vue-contextmenu'
Vue.use(VueContextMenu)

2.1 普通列表菜单
2.1.1 完整代码

<template>
  <div 
    id="app" @contextmenu="showMenu"
    style="width: 200px;height: 200px;margin-top: 20px;background: pink;">
    <vue-context-menu 
      :contextMenuData="contextMenuData" @deleteData="deleteData" @newAdd="newAdd">
    </vue-context-menu>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 菜单数据
      contextMenuData: {
        menuName: 'demo',
        // 菜单显示的位置
        axis: {
          x: null,
          y: null
        },
        // 菜单选项
        menulists: [
          {
            fnHandler: 'deleteData', // 绑定事件
            icoName: 'el-icon-delete', // 图标 (本文取自 element-ui)
            btnName: '保存' // 菜单名称
          },{
            fnHandler: 'newAdd',
            icoName: 'el-icon-plus',
            btnName: '新增'
          }
        ]
      }
    };
  },
  methods: {
    showMenu () {
      event.preventDefault()
      var x = event.clientX;
      var y = event.clientY;
      // 获取当前位置
      this.contextMenuData.axis = { x, y }
    },
    // 删除
    deleteData () {},
    // 新增
    newAdd () {}
  },
  watch: {},
};
</script>

2.1.2 效果
在这里插入图片描述
2.2 树型菜单
2.2.1 完整代码

<template>
  <div style="position: fixed; left: 0px; top: 0">
    <div
      @contextmenu="showMenu(index)"
      style="width: 100px; height: 100px; margin-top: 20px; background: red"
      v-for="(n, index) in 2"
      :key="n"
    >
      <vue-context-menu
        :contextMenuData="contextMenuData"
        :transferIndex="transferIndex"
        @Handler1="Handler_A(index)"
        @Handler2="Handler_B(index)"
        @Handler3="Handler_C(index)"
      ></vue-context-menu>
    </div>
  </div>
</template>
<script>
export default {
  name: "app",
  data() {
    return {
      transferIndex: null,
      contextMenuData: {
        menuName: "demo",
        axis: {
          x: null,
          y: null,
        },
        menulists: [
          {
            btnName: "选项1",
            icoName: "el-icon-s-tools",
            children: [
              {
                icoName: "el-icon-download",
                btnName: "选项1-1",
                // 子菜单
                children: [
                  {
                    icoName: "el-icon-share",
                    btnName: "选项1-1-1",
                    children: [
                      {
                        icoName: "el-icon-switch-button",
                        fnHandler: "Handler1",
                        btnName: "选项1-1-1",
                      },
                    ],
                  },
                ],
              },
            ],
          },
          {
            btnName: "选项2",
            children: [
              {
                fnHandler: "Handler2",
                btnName: "选项2-1",
              },
            ],
          },
          {
            btnName: "选项3",
            fnHandler: "Handler3",
          },
          {
            btnName: "选项4",
            disabled: true,
          },
        ],
      },
    };
  },
  methods: {
    showMenu(index) {
      this.transferIndex = index; // 将索引转换到子组件
      event.preventDefault();
      var x = event.clientX;
      var y = event.clientY;
      this.contextMenuData.axis = { x,y };
    },
    Handler_A(index) {
      console.log(index, "选项 1-1-1 绑定事件执行");
    },
    Handler_B(index) {
      console.log(index, "选项 2-1 绑定事件执行");
    },
    Handler_C(index) {
      console.log(index, "选项 3 绑定事件执行");
    },
  },
};
</script>

<style>
* {
  margin: 0;
  padding: 0;
}
</style>

2.2.2 效果
在这里插入图片描述

参考文章

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/141401.html

(1)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!