• 在vue中点击右键出现自定义操作菜单


    在vue中点击右键出现自定义操作菜单

    在网页中我们也希望可以像桌面软件一样,点击右键后出现操作菜单,对选中的数据项进行相应的操作,接下来就为大家介绍使用原生vue进行右键出现菜单的方法,并贴上详细介绍的代码

    最终效果

    在这里插入图片描述

    代码

    这个是我们要进行点击的时候点击的目标组件

    • @contextmenu.prevent.stop 为阻止浏览器的右键点击菜单事件
    • 我们的菜单相当于是独立于原本所在的内容的,所以原本的内容使用一个 div 包起来,menu 另外包起来
    • 同时我们要为其出现的地方进行调整 menuTop,menuLeft,在展示 menu 的时候我们将 event 的页面位置属性 e.pageX 和 e.pageX 拿来赋值
    • isShowMenu: 来控制菜单的显示
    • hiddenMenu: 是为了方便我们的菜单子组件在进行对应的操作以后要使菜单消失
    • :conversation: 就是我们要执行操作的数据项了
    • 我们需要在页面创建的时候增加 clickmousedonw 的监听,这样就可以在我们点击别的地方的时候将菜单隐藏
    <template>
        <div class = "conversation-info" @contextmenu.prevent.stop="showMenu">
            <div class="wrapper" >
                <el-badge
                    :value="conversation.unreadNum"
                    :hidden="conversation.unreadNum === 0">
                    <div class="conversation-avatar">
                    <el-avatar shape="square" size="large" :src="conversation.photo"></el-avatar>
                    </div>
                </el-badge>
                <div class="conversation-detail">
                    <div class="top-item">
                    <div class="ellipsis">
                        <span>{{ conversation.name }}</span>
                    </div>
                    <div>
                        <span style="font-size:12px;">{{ conversation.createTime | formatDateToZH }}</span>
                    </div>
                    </div>
                    <div class="bottom-item ellipsis">
                    <span class="conversation-message">
                        {{ conversation.message }}
                    </span>
                    </div>
                </div>
            </div>
            <div class="menu" v-if="isShowMenu" :style="{'left': menuLeft + 'px', 'top': menuTop + 'px'}">
              <home-menu
                :conversation="conversation"
                @hiddenMenu="hiddenMenu"
              />
            </div>
        </div>
    </template>
    <script>
    import homeMenu from '@/components/menu/HomeMenu'
    import {formatDateToZH} from '@/utils'
    export default {
      name: 'ConversationItem',
      components: { homeMenu },
      props: ['conversation'],
      data () {
        return {
          isShowMenu: false,
          menuTop: 0,
          menuLeft: 0
        }
      },
      filters: {
        formatDateToZH (val) {
          return formatDateToZH(val)
        }
      },
      created () {
        document.addEventListener('click', () => {
          this.isShowMenu = false
        })
        document.addEventListener('mousedown', (e) => {
          const {button} = e
          if (button === 2) {
            this.isShowMenu = false
          }
        })
      },
      methods: {
        showMenu (e) {
          this.isShowMenu = true
          this.menuLeft = e.pageX
          this.menuTop = e.pageY
        },
        hiddenMenu () {
          this.isShowMenu = false
        }
      }
    }
    </script>
    <style>
    .conversation-info {
      height: 60px;
      padding: 0 10px 0;
      background-color: #e6e6e6;
    }
    .conversation-info .active {
      height: 60px;
      padding: 0 10px 0;
      background-color: #cfcfcf;
    }
    .conversation-info:hover {
      height: 60px;
      padding: 0 10px 0;
      background-color: #cfcfcf;
    }
    .conversation-info .menu {
        position: fixed;
        z-index: 1004;
        background-color: #fff;
        border-radius: 5px;
    }
    .conversation-info .wrapper {
      display: flex;
      height: 60px;
      padding: 0 5px;
      align-items: center;
      border-radius: 10px;
      overflow: hidden;
    }
    .el-badge {
      top: 4px;
      overflow: visible;
    }
    .conversation-avatar {
      width: 40px;
      height: 40px;
    }
    .conversation-detail {
      margin-left: 10px;
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    .top-item {
      height: 20px;
      width: 260px;
      display: flex;
      flex-direction: row;
      justify-content: space-between;
    }
    .bottom-item {
      height: 14px;
      margin-top: 6px;
      font-size: 12px;
      color:#968b8b;
      width: 200px;
    }
    .conversation-message {
      float: left;
    }
    .ellipsis{
      display: inline-block;
      overflow: hidden;
      text-overflow:ellipsis;
      white-space: nowrap;
    }
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145

    这个就是我们真正的菜单组件了

    • props: ['conversation']: 方便我们接受数据,以便在点击对应菜单后进行相应的操作
    • this.$emit('hiddenMenu'): 表示我们在执行完成该菜单操作后向父组件进行通讯,让其关闭菜单
    <template>
      <div class="conversation-item-menu box-shadow1">
        <span class="menu-item operation-text" @click.stop="remove">关闭会话</span>
        <span class="menu-item operation-text" @click.stop="stick">置顶</span>
        <span class="menu-item operation-text" @click.stop="notShow">不显示会话</span>
        <el-popover
          placement="top"
          width="160"
          v-model="showDelPop">
          <p>删除会话后聊天记录等信息也会被删除,是否删除?</p>
          <div style="text-align: right; margin: 0">
            <el-button size="mini" type="text" @click="showDelPop = false">取消</el-button>
            <el-button type="primary" size="mini" @click.stop="deleteConversation">确定</el-button>
          </div>
          <span slot="reference" class="menu-item operation-text" @click.stop="()=>{}">删除会话</span>
        </el-popover>
      </div>
    </template>
    
    <script>
    export default {
      name: 'HomeMenu',
      props: ['conversation'],
      data () {
        return {
          showDelPop: false,
          friendInfo: {}
        }
      },
      computed: {
        userInfo () {
          return this.$store.state.user.userInfo
        }
      },
      methods: {
        remove () {
          console.log('删除:', this.conversation.name)
          this.$emit('hiddenMenu')
        },
        stick () {
          console.log('置顶:', this.conversation.name)
          this.$emit('hiddenMenu')
        },
        notShow () {
          console.log('不显示会话:', this.conversation.name)
          this.$emit('hiddenMenu')
        },
        deleteConversation () {
          console.log('删除会话:', this.conversation.name)
          this.$emit('hiddenMenu') // 关闭菜单
        }
      }
    }
    </script>
    
    <style>
    .conversation-item-menu {
      padding: 5px;
    }
    .box-shadow1 {
      box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
    }
    .menu-item {
        display: block;
        margin-top: 5px;
    }
    .operation-text {
      cursor: pointer;
      padding: 2px 4px;
      border-radius: 3px;
      color: #7e7e7e;
      transition: all .5s ease-in;
    }
    .operation-text:hover {
      background-color: #E9EAEC;
    }
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
  • 相关阅读:
    软件测试功能测试全套常见面试题【功能测试-零基础】必备4-1
    自定义Lua解析器管理器-------演化脚本V0.5
    Linux操作系统:多进程拷贝
    设计模式简要总结
    Docker网络模型(五)使用 overlay 网络
    【Go语言】项目实战:客户信息管理系统(需求分析、项目设计、功能实现)
    【PyTorch 攻略(5/7)】训练和模型
    局域网内vue2 配置本地IP地址访问项目
    qt生成帮助文档过程
    引力搜索算法(Gravitational_Search_algorithm,GSA)附matlab代码
  • 原文地址:https://blog.csdn.net/qq_45803593/article/details/125407278