需求小能手——自定义右键菜单

371 阅读1分钟

前言

鼠标右键菜单想必大家都不陌生,在我们日常开发中可能需要自定义一下右键菜单,让右键菜单列表变成我们想要的列表,本节我们就来自定义一个右键菜单组件。

contextmenu

contextmenu事件是我们右键点击鼠标时触发的事件。当用户单击鼠标右键时,浏览器就会触发contextmenu事件,然后显示出菜单列表。该事件跟click、keyup等事件一样是在HTML元素上注册的,如果我们在vue中使用的话也是通过@来调用。

 <template>
  <div @contextmenu="showMenu">Right-click</div>
</template>
<script>
export default {
  methods: {
    showMenu(event) {
      console.log('点击了右键');
    }
  }
};
</script>

菜单组件

自定义的菜单组件肯定需要通过contextmenu时间来触发,但是现在右键出现的是默认菜单列表,怎么让默认菜单不再出现?通过preventDefault来阻止默认事件即可。我们在组件中监听contextmenu并且阻止它的默认事件,然后换上我们自定义的事件。

    window.addEventListener('contextmenu', e => {
          e.preventDefault();
          //触发自定义事件
          this.showMenu();
        });

这样核心代码我们就得到了,我们自定义菜单主要是为了改变菜单的样式和功能,样式一般可以固定,而具体功能可能有所不同,所以我们可以定义options参数来接受菜单展现的数据。至此我们静态页面就能得到,菜单样式我们可以根据需要自定义。

   template>
  <div>
    <ul :id="elementId" v-click-outside="onClickOutside" class="vue-simple-context-menu">
      <li
        v-for="(option, index) in options"
        :key="index"
        class="vue-simple-context-menu__item"
        @click="optionClicked(option)"
      >{{ option.name }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'VueContextMenu',
  props: {
    //菜单id
    elementId: {
      type: String,
      required: true
    },
    //菜单项
    options: {
      type: Array,
      required: true
    }
  },
  data() {
    return {
      item: null,
      menuWidth: null,
      menuHeight: null
    }
  }
}
</script>
<style lang="scss">
</style>

接下来补充对应的功能即可,我们需要根据不同选项去执行不同的效果,利用$emit传递参数在父组件执行对应的时间。我们也可以直接写死对应的事件,然后就是showMenu事件,我们需要获取当前坐标位置,将菜单定位点击位置附近。

    methods: {
    //计算菜单位置
    showMenu(item) {
      const event = window.event || event
      this.item = item
      const menu = document.getElementById(this.elementId)
      if (!menu) {
        return
      }
      if (!this.menuHeight) {
        menu.style.visibility = 'hidden'
        menu.style.display = 'block'
        // this.menuWidth = menu.offsetWidth
        this.menuHeight = menu.offsetHeight
        menu.removeAttribute('style')
      }
      if (this.menuWidth + event.pageX) {
        menu.style.left = event.pageX - this.menuWidth + 2 + 'px'
      } else {
        menu.style.left = event.pageX - 2 + 'px'
      }

      if (this.menuHeight + event.pageY >= window.innerHeight) {
        menu.style.top = event.pageY - this.menuHeight + 2 + 'px'
      } else {
        menu.style.top = event.pageY - 2 + 'px'
      }
      menu.classList.add('vue-simple-context-menu--active')
    },
    //点击菜单外区域隐藏菜单
    onClickOutside() {
      this.hideContextMenu()
    },
     hideContextMenu() {
      const element = document.getElementById(this.elementId)
      if (element) {
        element.classList.remove('vue-simple-context-menu--active')
      }
    },
    //菜单项触发事件并且隐藏菜单
    optionClicked(option) {
      this.$emit('option-clicked', { item: this.item, option: option })
      this.hideContextMenu()
    }
  }

总结

以上就是自定义右键菜单,主要运用contextmenu事件,我们可以根据自己需要去做相关优化。