vue 实现弹出菜单,解决鼠标点击其他区域的检测问题

弹出菜单应该具有的功能,当鼠标点击其他区域时,则关闭该菜单。
问题来了,怎么检测鼠标点击了其他区域而不是当前菜单?
百度“JS检测区域外的点击事件”,会发现有很多方法,有递归检测父元素,有遍历冒泡节点等等。
vue 解决的思路:将菜单区域的点击事件用 stop 修饰,在最顶层元素调用鼠标单击事件关闭菜单,完毕!
由于菜单区域单击事件已被 stop 停止冒泡,顶层元素无法捕获,因此菜单区域的单击并不会关闭自己。这样,不需要增加任何逻辑代码,只需要在单击事件后增加一个 .stop 后缀来修饰就能解决。

演示效果和源码如下:
在这里插入图片描述

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.min.js"></script>
    <title>弹出菜单测试1</title>
    <style>
        body {padding: 0; margin: 0;}
        #base {
            width: 100%;
            height: 100%;
            position: absolute;
        }
        #nav { margin: 16px;}
        #nav>span {
            display: inline-block;
            border: 1px solid #bbb;
            background-color: #ebf4f6;
            border-radius: 6px;
            padding: 6px 18px;
            user-select: none;
        }
        #nav>span:hover {background-color: #ace4eb;}
        .menu>div {
            display: flex;
            justify-content: flex-start;
            flex-direction: column;
            width: 160px;
            border: 1px solid #bbb;
            border-radius: 6px;
            padding: 12px 0;
            box-shadow: 0px 0px 5px #999;
            position: absolute;
        }
        .menu>div>div {
            width: 148px;
            height: 32px;
            margin: 0 6px;
            line-height: 32px;
            border-radius: 4px;
            text-align: center;
        }
        .menu>div>div:hover {background-color: #ace4eb;}
        hr {
            width: 154px;
            height: 1px;
            color: #808080;
            margin: 5px 2px;
        }
    </style>
</head>
<body>
    <div id="base" @click="pickOther">
        <div id="nav" @click.stop="showMenu">
            <span id="ck1">手机</span>
            <span id="ck2">电脑</span>
            <span id="ck3">家具</span>
        </div>
        <div @click.stop="pickMenu" class="menu">
            <div v-if="cMenu=='ck1m'" id="ck1m">
                <div>手机通讯</div>
                <div>手机配件</div>
                <div>运营商</div>
                <div>智能设备</div>
            </div>
            <div v-if="cMenu=='ck2m'" id="ck2m">
                <div>电脑整机</div>
                <div>电脑配件</div>
                <hr>
                <div>外设产品</div>
                <div>游戏设备</div>
                <div>游戏设备</div>
                <div>办公设备</div>
            </div>
            <div v-if="cMenu=='ck3m'" id="ck3m">
                <div>家电厨具</div>
                <div>家装软饰</div>
                <div>生活日用</div>
                <div>灯具五金</div>
            </div>
        </div>
    </div>
    <script>
        var vm = new Vue({
            el: '#base',
            data: { cMenu: '' },  // cMenu 为空时不显示任何菜单
            methods: {
                showMenu: function () {
                    const btn = event.target;
                    if (btn.nodeName.toUpperCase() != 'SPAN') return;
                    // 计算菜单的新坐标
                    const e = $(btn);
                    const x = e.offset().left + e.innerWidth();
                    const y = e.offset().top + e.innerHeight();
                    // 弹出菜单跟随按钮位置而移动,这里需要二次渲染(1 显示菜单,2 移动菜单)
                    const id = btn.id + 'm';
                    this.cMenu = id;
                    this.$nextTick(e => { $('#' + id).css({ "top": y, "left": x }); });
                },
                // 鼠标点击全部区域,菜单区域的单击被阻断冒泡不会触发此函数
                pickOther: function () { this.cMenu = ''; },
                // 点击菜单区域时,给出当前点击的菜单名
                pickMenu: function () { console.log($(event.target).text()); }
            }
        });
    </script>
</body>
</html>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要在Vue实现自定义的鼠标右键菜单,你可以借助第三方插件或者自己编写代码来实现。下面是一个使用第三方插件 `vue-contextmenu` 的示例: 首先,安装 `vue-contextmenu` 插件: ```shell npm install vue-contextmenu ``` 然后,在你的Vue项目中,导入并注册 `vue-contextmenu` 插件: ```javascript import VueContextmenu from 'vue-contextmenu'; Vue.use(VueContextmenu); ``` 接下来,在需要添加右键菜单的元素上使用 `v-contextmenu` 指令,并绑定一个方法来定义菜单的内容和行为: ```html <template> <div> <div v-contextmenu="contextMenu"> Right-click me! </div> </div> </template> <script> export default { data() { return { contextMenu: [ { text: '菜单项1', action: 'menuItem1' }, { text: '菜单项2', action: 'menuItem2' }, { text: '菜单项3', action: 'menuItem3' } ] }; }, methods: { menuItem1() { console.log('执行菜单项1的操作'); }, menuItem2() { console.log('执行菜单项2的操作'); }, menuItem3() { console.log('执行菜单项3的操作'); } } }; </script> ``` 在这个例子中,`contextMenu` 数组定义了右键菜单的内容,每个菜单项都有一个 `text` 属性用于显示菜单项的文本,以及一个 `action` 属性用于定义菜单项被点击时要执行的方法。 运行项目后,当你在指定的元素上右键点击时,就会弹出自定义的右键菜单,并执行相应的方法。 除了使用第三方插件外,你也可以根据需求自己编写代码来实现自定义的鼠标右键菜单。这需要使用原生JavaScript事件来捕获右键点击事件,并自定义菜单的样式和行为。 希望对你有所帮助!如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yxp_xa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值