上下文菜单,通过Teleport穿透到body,但是菜单按钮点击事件怎么点都没反应,下面是上下文菜单组件代码(其他小伙伴写的),现在要我来改bug.
<template>
<div>
<Teleport to="body">
<div class="workflow_contextmenu" :style="bStyle">
<div
class="workflow_contextmenu_item"
v-for="item in props.menu"
:key="item.code"
@click.stop="handleClickItem(item.code)"
>
{{ item.name }}
</div>
</div>
</Teleport>
</div>
</template>
<script setup>
const props = defineProps({
menu: {
type: Array,
default: () => [{ name: '删除', code: 1 }],
},
pos: {
type: Object,
default: () => {
return {
x: 0,
y: 0,
}
},
},
})
const emits = defineEmits(['close', 'click'])
const bStyle = reactive({
top: props.pos.y + 'px',
})
// 菜单位置控制 可以不看
watch(
() => props.pos,
(newValue) => {
const maxWidth = document.body.offsetWidth - 200
const maxHeight = document.body.offsetHeight - props.menu.length * 30 - 20
if (newValue.x < maxWidth) {
bStyle.left = newValue.x + 'px'
} else {
bStyle.right = maxWidth - newValue.x + 235 + 'px'
}
if (newValue.y < maxHeight) {
bStyle.top = newValue.y + 'px'
} else {
bStyle.top = maxHeight + 'px'
}
},
{ deep: true, immediate: true }
)
const closeMenu = () => {
emits('close')
}
const handleMouse = (event) => {
if (event.button === 0) {
setTimeout(() => {
closeMenu()
}, 100)
}
}
// 点击事件怎么都没有反应
const handleClickItem = (code) => {
emits('click', code)
emits('close')
}
onMounted(() => {
window.addEventListener('mousedown', handleMouse, false)
})
onUnmounted(() => {
window.removeEventListener('mousedown', handleMouse, false)
})
</script>
<style lang="less" scoped>
.workflow_contextmenu {
position: fixed;
cursor: pointer;
width: 200px;
padding: 5px 0;
background-color: #ffffff;
border-radius: 4px;
border: 1px solid #ebeef5;
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
box-sizing: border-box;
.workflow_contextmenu_item {
font-size: 14px;
color: #333333;
padding: 3px 10px;
&:hover {
color: #409eff;
}
}
}
</style>
简单说下代码,template渲染上下文菜单,接受菜单数据,位置作为props,然后就是动态样式,菜单事件。就是上面这个handleClickItem事件怎么点击都没有反应
尝试方法1 给组件z-index
刚开始以为是z-index属性,是不是页面把上下文菜单给遮住了,导致没有触发,于是在bStyle里加z-index给到9999, 还是不行
尝试方法2 看到页面有mousedown事件,看看能不能执行
页面有window.addEventListener('mousedown', handleMouse, false), 在handleMouse里加了断点,发现可以执行,那就说明这个页面事件机制是正常的,只是按钮的click事件有问题。
然后发现点击菜单按钮,mouseMove事件也执行了,(说的过去,因为点击按钮也要按下鼠标),仔细看了mouseMove事件方法,发现有一句, setTimeout(() => { closeMenu() }, 100) 是不是mousedown鼠标按下后马上就关闭了菜单,导致点击事件没来得及执行。
修复方案 注释mousedown事件
// onMounted(() => {
// window.addEventListener('mousedown', handleMouse, false)
// })
// onUnmounted(() => {
// window.removeEventListener('mousedown', handleMouse, false)
// })
注释了mousedown'事件,发现按钮可以正常点击了。果然是mousedown关闭了菜单按钮点击事件没来得及触发。发现按钮自己的点击方法里有emits('close')事件,所以没影响,唯一影响的是点击上下文菜单空白地方,菜单不会关闭。
感觉这是符合用户体验的。只有点击按钮才会关闭,或点击页面出菜单外空白处,到此,这个bug解决了。