当前位置:首页 > 开发教程 > js/jQuery教程 >

vue实现自定义全局右键菜单

时间:2022-04-09 09:36 来源:未知 作者:无恙 收藏

这篇文章主要为大家详细介绍了vue实现自定义全局右键菜单,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

前段时间公司在做一个webIDE项目,其中有对文件树的各种操作,主要通过右键菜单实现,今天就来记录一下怎么在vue项目中实现全局的自定义右键菜单。效果如图所示:

vue实现自定义全局右键菜单

注意:

需要在项目中找到页面整体布局的组件,比如项目使用Home.vue作为整个项目的公共布局,将根元素定位设置成relative,使右键菜单相对于其进行定位。

本文的右键菜单主要使用vuex实现

一、vuex中定义全局状态用于管理右键菜单

export default {
  /**
  * menuContent格式:
  * [
  *   {
  *     name: '新建文件',  // 操作名
  *     method: 'createDirectory', // 需要执行的对应组件中的方法
  *    disabled: true  // 是否禁用,可以根据页面具体逻辑进行调整
  *   }
  * ]
  *
  *
  * 整体右键菜单采用绝对定位,所以clientX、clientY代表是left和top定位
  */
  state: {
    menuContent: [],  // 右键菜单内容
    clientX: '',  // left
    clientY: '',  // top
    displayContextMenu: false  // 是否展示右键菜单
  },
  mutations: {
    SET_CONTEXT_MENU: (state, payload) => {
      state.menuContent = payload.menuContent;
      state.clientX = payload.clientX;
      state.clientY = payload.clientY;
      state.displayContextMenu = payload.displayContextMenu;
    },
  }
}

二、定义公共组件ContextMenu.vue

<template>
  <div class="context-menu" v-show="contextMenu.displayContextMenu"
    :style="{'left': contextMenu.clientX + 'px', 'top': contextMenu.clientY + 'px'}">
    <ul>
      <li v-for="(item, i) in contextMenu.menuContent" :key="i" :class="item.disabled  'disabled' : ''"
        @click="emitEvent(item.method)">
        {{item.name}}
      </li>
    </ul>
  </div>
</template>

<script>
import { mapState } from 'vuex';
import bus from '@/views/common/bus';
export default {
  name: 'ContextMenu',
  data(){
    return {
    }
  },
  computed: {
    ...mapState(['contextMenu'])
  },
  methods: {
    emitEvent(type){
      bus.$emit('operateDirectory', type)
    }
  }
}
</script>

<style lang="scss" scoped>
  .context-menu {
    position: absolute;
    background: #FFF;
    color: #34495E;
    min-width: 100px;
    box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.2);
    border-radius: 2px;
    cursor: pointer;
    z-index: 1002;
    &>ul {
      text-align: left;
      padding: 5px 10px;
      &>li {
        padding: 3px 4px;
        font-size: 12px;
        list-style: none;
        height: 24px;
        line-height: 24px;
        &:hover {
          background: #EDF6FF;
        }
      }
      .disabled {
        color: #888585;
        pointer-events: none;
      }
    }
  }
</style>

三、在组件中使用

import { mapState } from 'vuex';
// ...

computed: {
 ...mapState(['contextMenu'])
},
created(){
 bus.$on('operateDirectory', (param) => {
 // 点击右键菜单时,应触发组件内的同名方法,首先应判断该方法是否在本组件内存在,存在则调用
  if(this[param]){
   this[param]();
  }
 });
},
// ...

methods: {
 showContextMenu(event, data) {
    event.preventDefault();  // 阻止浏览器的默认事件
    const menuContent = {
      menuContent: [
      {
        icon: "el-icon-upload2",
        name: "运行",
        method: "run",
      },
      {
        icon: "el-icon-refresh",
        name: "编辑",
        method: "editConfig",
      },
      {
        icon: "el-icon-refresh",
        name: "添加",
        method: "addCommond",
      },
      {
        icon: "el-icon-refresh",
        name: "删除",
        method: "deleteConfig",
      },
      ],
      clientX: event.clientX,
      clientY: event.clientY,
      displayContextMenu: true,
    };
    this.$store.commit("SET_CONTEXT_MENU", menuContent);
    // 再次点击页面,右键菜单消失
    document.onclick = (event) => {
      this.$store.commit("SET_CONTEXT_MENU", {
        displayContextMenu: false,
      });
    };
  },
  run(){
  // ...
 },
 editConfig(){
  // ...
 },
 addCommond(){
  // ...
 },
 deleteConfig(){
  // ...
 }
}

总结

这种可以实现全局右键菜单,并且支持自定义右键内容,但是vue3.0对event bus的取消会导致不可用。

目前有一种优化方法:项目中对应会使用组件库,例如element ui,在定义contextMenu.vue的时候,使用dialog,将内容定义在Popover 弹出框中,当组件使用右键菜单时,使用子组件的方式使用ContextMenu.vue,点击右键菜单内容时就不需要使用emit触发了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持源码搜藏网。


下一篇:没有了

js/jQuery教程阅读排行

最新文章