VUE 鼠标右键菜单

1.组件,分为Index.Vue,和Item.vue

1.此文件为index.Vue
<template> <transition name="fade"> <div class="elx-context-menu" v-show="visible" :style="{width: width+'px', top: currentY+'px', left: currentX+'px'}"> <ul> <context-menu-item v-for="item in data" :key="item.label" :data="item" :tip-show="tipShow" @action="action"> </context-menu-item> </ul> </div> </transition> </template> <script> import ContextMenuItem from './item'; export default { name: 'ContextMenu', componentName: 'ContextMenu', components: { ContextMenuItem }, props: { width: {// type: Number, default: 80 }, x: {// X坐标 type: Number, default: 0 }, y: {// Y坐标 type: Number, default: 0 }, data: {// 显示右键菜单的数据 type: Array, default: function() { return []; } }, visible: {// 是否显示右键菜单 type: Boolean, default: false }, tipShow: {// 是否显示提示 type: Boolean, default: true } }, data() { return { currentX: 0, currentY: 0 }; }, methods: { action(data) { if (!data.disabled) { this.$emit('action', data); } }, changePos() { const gap = 5; const bodyClientHeight = document.body.clientHeight; const bodyClientTop = document.body.clientTop; const height = this.$el.clientHeight; const elBottom = height + this.currentY; const viewHeight = bodyClientHeight + bodyClientTop; if (viewHeight < elBottom) { this.currentY = viewHeight - height - gap; } }, handleDisplay() { this.contentMenuShow = false; } }, watch: { visible(val) { if (val) { const self = this; self.$nextTick(() => { self.changePos(); }); } }, x(val) { this.currentX = val; }, y(val) { this.currentY = val; this.changePos(); } }, created() { this.currentX = this.x; this.currentY = this.y; }, mounted() { this.changePos(); window.addEventListener('resize', this.handleDisplay); }, beforeDestroy() { window.removeEventListener('resize', this.handleDisplay); } }; </script>

2.item.vue


此文件为item.Vue
<template>

  <li
    :class="data.disabled?'disabled':''"
    @click.stop.prevent="exec"
    @mouseenter.stop.prevent="showChild"
    @mouseleave.stop.prevent="hideChild">
    <el-tooltip :content="data.label" placement="left" :hide-after="500" v-if="tipShow">
      <div class="elx-context-menu-title">
        <span :class="data.class">
          <span v-if="data.icon" :class="data.icon"></span>
          <span v-if="data.label" v-text="data.label"></span>
          <!-- <node-content :node="data"></node-content> -->
        </span>
        <template v-if="'children' in data">
          <span v-if="data.children.length>0" class="uex-icon-caret-right"></span>
        </template>
      </div>
    </el-tooltip>
    <div class="elx-context-menu-title" v-if="!tipShow" :title="data.label">
      <span :class="data.class">
        <span v-if="data.icon" :class="data.icon"></span>
         <span v-if="data.label" v-text="data.label"></span>
        <!-- <node-content :node="data"></node-content> -->
      </span>
      <template v-if="'children' in data">
        <span v-if="data.children.length>0" class="uex-icon-caret-right"></span>
      </template>
    </div>
    <ul
      v-if="'children' in data" v-show="visible" :style="{top: pos.top, bottom: pos.bottom}"> <context-menu-item v-for="(item,index) in data.children" :key="index" :data="item" @action="action"> </context-menu-item> </ul> </li> </template> <script> export default { name: 'ContextMenuItems', componentName: 'ContextMenuItems', props: { data: { type: Object, default() { return {}; } }, tipShow: { type: Boolean, default: false } }, components: {}, data() { return { pos: { top: '0px', bottom: 'auto' }, visible: false }; }, methods: { getElementPosition(el) { let x = 0; let y = 0; while (el != null) { x += el.offsetLeft; y += el.offsetTop; // eslint-disable-next-line no-param-reassign el = el.offsetParent; } return { x, y }; }, exec() { if (!this.data.disabled) { this.$emit('action', this.data); } }, action(data) { if (!data.disabled) { this.$emit('action', data); } }, changeStyle() { const self = this; if (self.$el.childNodes[1]) { if (typeof self.$el.childNodes[1].tagName === 'string') { if (self.$el.childNodes[1].tagName.toLowerCase() === 'ul') { const bodyClientHeight = document.body.clientHeight; const bodyClientTop = document.body.clientTop; const viewHeight = bodyClientHeight + bodyClientTop; const clientTop = this.getElementPosition(self.$el.childNodes[1]).y; const height = self.$el.childNodes[1].clientHeight; const elBottom = height + clientTop; if (viewHeight < elBottom) { this.pos.top = 'auto'; this.pos.bottom = '0px'; } else { this.pos.top = '0px'; this.pos.bottom = 'auto'; } } } } }, showChild() { this.visible = true; }, hideChild() { this.visible = false; this.pos.top = '0px'; this.pos.bottom = 'auto'; } }, watch: { visible(val) { if (val) { const self = this; this.$nextTick(() => { self.changeStyle(); }); } } }, created() { }, mounted() { this.changeStyle(); } }; </script>

3.调用组件:

import ContextMenu from './content-menu/index';

// 我这里是表格调用
  @row-contextmenu="rowContextmenu1",在表格中放入改事件,放在el-table上,
// 组件
//data数据
 contextmenuData: [
                { label: '新增', action: 'add', icon: 'ri-add-line' },
                { label: '编辑', action: 'edit', icon: 'ri-edit-box-line', disabled: true },
                { label: '删除', action: 'delete', icon: 'ri-delete-bin-7-line' }
            ],

pos: {
                x: 0,
                y: 0
            },
rowContextmenu: false,
//html
<ContextMenu
                    @action="action"
                    :tip-show="false"
                    :data="contextmenuData"
                    :width="120"
                    :visible="rowContextmenu"
                    :x="pos.x"
                    :y="pos.y">
            </ContextMenu>
//js事件
  getEventPos(e) {
            const x = e.clientX;
            const y = e.clientY;
            return { x, y };
        },
        rowContextmenu1(row) {
            console.log('row', row);
            const contextmenuData = [
                { label: '新增', action: 'add', icon: 'ri-add-line' },
                { label: '编辑', action: 'edit', icon: 'ri-edit-box-line', disabled: true },
                { label: '删除', action: 'delete', icon: 'ri-delete-bin-7-line' }
            ];
            const e = window.event;
            const pos = this.getEventPos(e);
            if (e.which === 3) {
                this.rowContextmenu = false;
                this.pos.x = pos.x;
                this.pos.y = pos.y;
                this.contextmenuData = contextmenuData;
                this.rowContextmenu = true;
            }
            this.preventDefault(e);
            e.returnValue = false;
            return false;
        },
        preventDefault(el) {
            const e = el || window.event;
            if (e.preventDefault) {
                e.preventDefault();
            } else {
                e.returnvalue = false;
            }
            return e;
        },
        action(data) {
            console.log('data.action', data.action);
            this.rowContextmenu = false;
        },

这只是我项目中一个简单的demo,有问题,私信我

猜你喜欢

转载自www.cnblogs.com/wangliko/p/13208922.html