首页 > 解决方案 > Vuejs 3 - 自定义上下文菜单的问题

问题描述

我有这个上下文菜单,你可以在网上找到。我想访问按钮的单击事件以打开引导模式。问题是当我将@blur属性设置为关闭函数时,我无法再处理点击事件。似乎单击事件会被触发,因为 div 事先已关闭。即使我单击不正确的按钮,上下文菜单也会自行关闭。只有当我在 div 外部单击时,它才会关闭。有解决方法吗?

<template>
    <div class="context-menu" v-show="show" :style="style" ref="context" tabindex="0" @blur="close">
        <button @click="handle" class="btn btn-outline-secondary">Create Object</button>
    </div>
</template>

<script>
import { nextTick } from '@vue/runtime-core';

export default {
    name: 'ContextMenu',
    data(){
        return {
            left: 0,
            top: 0,
            show: false,
        }
    },
    computed: {
        style() {
            return {
                top: this.top + 'px',
                left: this.left + 'px',
            };
        },
    },
    methods: {
        close() {
            console.log("closed")
            this.show = false;
            this.left = 0;
            this.top = 0;
        },
        open(e) {
            this.left = e.pageX || e.clientX;
            this.top = e.pageY || e.clientY;
            nextTick(() => this.$el.focus())
            this.show = true;
        },
        handle(){          
            console.log("clicked")
            //Do something
            this.close()
        }
    }
}
</script>

<style scoped>
.context-menu {
    position: fixed;
    background: white;
    z-index: 999;
    outline: none;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
    cursor: pointer;
}
</style>

标签: vuejs3

解决方案


这是因为您的 div 正在失去对按钮的关注。在您的按钮可以触发 click 事件之前,会在父 div 上触发 blur 事件。在您单击按钮的那一刻,这些事件会依次触发:

mousedown (button) -> blur (div) -> focus (button) -> mouseup (button) -> click (button)

const parent = document.getElementById("parent");
const button = document.getElementById("button");
const log = document.getElementById("log");

parent.focus();

parent.onblur = (e) => {
  const msg = document.createElement("div");
  msg.innerText = `parent blur: losing focus to #${e.relatedTarget?.id}`;
  log.appendChild(msg);
};

button.onmousedown = (e) => {
  const msg = document.createElement("div");
  msg.innerText = "button mousedown";
  log.appendChild(msg);
};

button.onmouseup = (e) => {
  const msg = document.createElement("div");
  msg.innerText = "button mouseup";
  log.appendChild(msg);
};

button.onclick = (e) => {
  const msg = document.createElement("div");
  msg.innerText = "button click";
  log.appendChild(msg);
};

button.onfocus = (e) => {
  const msg = document.createElement("div");
  msg.innerText = "button focus";
  log.appendChild(msg);
};

button.onblur = () => {
  const msg = document.createElement("div");
  msg.innerText = "button blur";
  log.appendChild(msg);
};
#parent {
  background: pink;
  padding: 20px;
}

#parent:focus {
  border: 1px solid blue;
}
<div id="parent" tabindex="0">
  <button id="button"> click me </button>
</div>

<div id="log">

</div>

在您的模糊处理程序中,您需要检查您失去焦点的元素是否仍在您的父 div 中。blur 事件有一个relatedTarget属性,它是接收焦点的元素。这个答案有一个任务的解决方案。


推荐阅读