鼠标右键点击菜单

<template>
  <div class="FitNavigation"
       @contextmenu.prevent="showMenu"
       @click.capture="ifShowMenu = false">
    <div
      class="functionMenu"
      ref="functionMenu"
      :style="ifShowMenu?{visibility:'visible'}:{visibility:'hidden'}"
      v-show="ifShowMenu"
      @click.stop
    >
      <ul class="functionMenu-ul">
        <li class="functionMenu-ul-li" @click.stop="ifFullScreen = false">
          <span class="functionMenu_left">
            {{$t('nav.Exit full screen')}}
          </span>
          <div class="functionMenu_right">
            <span>Esc</span>
          </div>
<!--          <ul-->
<!--            class="childrenSelect"-->
<!--            ref="exportAs"-->
<!--            :style="menu['exportAs'].position"-->
<!--          >-->
<!--            <li-->
<!--              class="childrenSelect-li"-->
<!--            >-->
<!--              -->
<!--            </li>-->
<!--          </ul>-->
        </li>
      </ul>
    </div>
      <slot></slot>
    </div>
</template>

<script>
  export default {
    name: "ContentMenu",
    data: () => ({
      drawer: true,
      ifFullScreen: false,
      ifShowMenu: false,
      client: {
        height: 0,
         0
      },
      menu: {
        height: 0,
         0,
        exportAs: {
          height: 0,
           0,
          position: {
            top: '0px',
            left: '0px'
          }
        }
      }
    }),
    mounted() {
      const cancelFullScreen = (event) => {
        event.stopPropagation();
        if (this.ifFullScreen && (event.key || event.code) === 'Escape') {
          this.ifFullScreen = false
        }
      };
      window.addEventListener('resize', this.initPX);
      document.addEventListener('keydown', cancelFullScreen);
      this.initPX();
      this.$once('hook:beforeDestroy', () => {window.removeEventListener('resize', this.initPX)});
      this.$once('hook:beforeDestroy', () => {document.removeEventListener('keydown', cancelFullScreen)});
    },
    methods: {
      initPX () {
        this.client.height = document.documentElement.clientHeight;
        this.client.width = document.documentElement.clientWidth;
        const computedSize = () => {
          if (this.$refs['functionMenu'] && this.menu.height !== 0 && this.menu.width !== 0) return;
          this.menu.height = this.$refs['functionMenu'].offsetHeight;
          this.menu.width = this.$refs['functionMenu'].offsetWidth;
          requestAnimationFrame(computedSize);
        };
        computedSize();
        // this.menu.exportAs.height = this.$refs['exportAs'].offsetHeight;
        // this.menu.exportAs.width = this.$refs['exportAs'].offsetWidth;
      },
      showMenu (el) {
        if (!this.ifFullScreen) return
        let left;
        let top;
        if (this.client.height - el.clientY < this.menu.height) {
          top = el.pageY - this.menu.height;
          this.menu.exportAs.position.top = `-${this.menu.exportAs.height - this.menu.height / (Object.keys(this.menu).length - 2)}px`;
        } else {
          top = el.pageY;
          if (this.client.height - el.clientY - this.menu.height < this.menu.exportAs.height) {
            this.menu.exportAs.position.top = `-${this.menu.exportAs.height - this.menu.height / (Object.keys(this.menu).length - 2)}px`;
          } else {
            this.menu.exportAs.position.top = '';
          }
        }
        if (this.client.width - el.clientX < this.menu.width) {
          left = el.pageX - this.menu.width;
          this.menu.exportAs.position.left = `-${this.menu.exportAs.width}px`;
        } else {
          left = el.pageX;
          if (this.client.width - el.clientX - this.menu.width < 100) {
            this.menu.exportAs.position.left = `-${this.menu.exportAs.width}px`;
          } else {
            this.menu.exportAs.position.left = '';
          }
        }
        this.$refs['functionMenu'].style.cssText = `left:${left}px;top:${top}px;`;
        this.ifShowMenu = true;
      }
    }
  }
</script>

<style lang="scss" scoped>
  .functionMenu {
    position: absolute;
     150px;
    background-color: white;
    z-index: 9999;
    box-shadow: 1px 1px 3px #111111;
    padding:5px 0;
    // color: @primary;
    color:black;
    font-size: 12px;
    &_left {
      float: left;
      margin-left: 2px;
    }
    &_right {
      float: right;
      margin-right: 2px;
      .icon-select {
        font-size:12px;
      }
      .icon-select:before {
        display:inline-block;
        transform:rotate(270deg);
      }
    }
    &-ul {
      line-height: 2;
      &-li {
        position: relative;
        padding-left:10px;
        &:after {
          content: "";
          display: block;
          clear: both;
        }
        &:hover {
          background-color: #9e9e9e;
          .childrenSelect {
            visibility: visible;
          }
        }
        .childrenSelect {
          visibility: hidden;
          position: absolute;
          left: 150px;
          top: 0;
          background: white;
           120px;
          padding:5px 0px;
          &:hover {
            display: block;
          }
          &-li {
            padding-left:10px;
            text-align:left;
            &:hover {
              background-color: #9e9e9e;
            }
          }
        }
      }
    }
  }
</style>
原文地址:https://www.cnblogs.com/smallZoro/p/12986067.html