Vue 中实现动态右键菜单
在前端开发中,自定义右键菜单是一种常见的交互方式,它能够为用户提供更多的功能选项。在本文中,将探讨如何在 Vue 中实现一个动态右键菜单,该菜单能够根据用户点击位置动态调整其显示位置,确保菜单始终在浏览器窗口的可视区域内。
实现目标
- 右键点击页面时显示自定义菜单。
- 菜单根据点击位置动态定位。
- 确保菜单不会超出浏览器窗口的可视区域。(超出窗口顶部或者底部优化)
实现步骤
1. 创建 Vue 组件模板
首先,编写 Vue 组件的模板部分:
<template>
<div v-if="visible">
<a-menu class="contextmenu" :style="style" @click="handleClick">
<a-menu-item v-for="item in list" :key="item.key">
<span>{{ item.text }}</span>
</a-menu-item>
</a-menu>
</div>
</template>
在这个模板中,使用 v-if
指令控制菜单的显示与隐藏,并使用 :style
绑定菜单的动态样式。
2. 编写组件脚本
接下来是组件的脚本部分:
<script>
export default {
name: "ContextMenu",
props: {
visible: {
type: Boolean,
default: false,
},
list: {
type: Array,
required: true,
default: () => [],
},
},
data() {
return {
left: 0,
top: 0,
target: null,
};
},
computed: {
style() {
return {
left: this.left + "px",
top: this.top + "px",
};
},
},
created() {
const clickHandler = () => this.closeMenu();
const contextMenuHandler = (e) => {
e.preventDefault();
this.setPosition(e);
};
window.addEventListener("click", clickHandler);
window.addEventListener("contextmenu", contextMenuHandler);
this.$emit("hook:beforeDestroy", () => {
window.removeEventListener("click", clickHandler);
window.removeEventListener("contextmenu", contextMenuHandler);
});
},
methods: {
closeMenu() {
this.$emit("update:visible", false);
},
setPosition(e) {
// 获取菜单的宽高
const menu = document.querySelector(".contextmenu");
const menuHeight = menu.offsetHeight;
// 获取窗口的可视高度
const windowHeight = window.innerHeight;
this.left = e.clientX;
// 计算菜单的上边位置
if (e.clientY + menuHeight > windowHeight) {
const top = e.clientY - menuHeight;
if (top < 0) {
this.top = 0; // 确保菜单不会超出顶部
} else {
// 如果菜单的底部超出了窗口的底部
this.top = top;
}
} else {
// 如果菜单的底部没有超出窗口的底部
this.top = e.clientY;
}
this.target = e.target;
},
handleClick({ key }) {
const _component = this.list.filter((item) => item.key === key)[0]
.component;
if (_component) {
this.$emit("contextMenuClick", _component, key);
}
this.closeMenu();
},
},
};
</script>
详细解释
setPosition
方法
setPosition
方法用于根据用户点击的位置动态调整菜单的位置,确保菜单始终在可视区域内。
setPosition(e) {
// 获取菜单的宽高
const menu = document.querySelector(".contextmenu");
const menuHeight = menu.offsetHeight;
// 获取窗口的可视高度
const windowHeight = window.innerHeight;
this.left = e.clientX;
// 计算菜单的上边位置
if (e.clientY + menuHeight > windowHeight) {
const top = e.clientY - menuHeight;
if (top < 0) {
this.top = 0; // 确保菜单不会超出顶部
} else {
// 如果菜单的底部超出了窗口的底部
this.top = top;
}
} else {
// 如果菜单的底部没有超出窗口的底部
this.top = e.clientY;
}
this.target = e.target;
}
- 相加:通过
e.clientY + menuHeight
计算菜单底部的位置,如果大于windowHeight
,则表示菜单超出了窗口底部,需要调整位置。 - 相减:通过
e.clientY - menuHeight
将菜单位置调整到鼠标点击位置的上方,确保菜单不会超出窗口底部。 - clientY:鼠标点击位置的垂直坐标,相对于视口。
- offsetHeight:菜单元素的高度,包括内容的高度、内边距和边框。
事件处理
在 created
生命周期钩子中,添加了 click
和 contextmenu
事件监听器。
created() {
const clickHandler = () => this.closeMenu();
const contextMenuHandler = (e) => {
this.setPosition(e);
};
window.addEventListener("click", clickHandler);
window.addEventListener("contextmenu", contextMenuHandler);
this.$emit("hook:beforeDestroy", () => {
window.removeEventListener("click", clickHandler);
window.removeEventListener("contextmenu", contextMenuHandler);
});
}
- clickHandler:点击页面时,关闭菜单。
- contextMenuHandler:右键点击时,阻止默认的右键菜单行为,并根据点击位置设置菜单的位置。
样式部分
<style lang="scss" scoped>
.contextmenu {
position: fixed;
z-index: 1000;
border-radius: 4px;
border: 1px lightgrey solid;
box-shadow: 4px 4px 10px lightgrey !important;
}
</style>
总结
通过以上代码,实现了一个动态右键菜单。这个菜单能够根据用户的点击位置动态调整其显示位置,确保菜单始终在浏览器窗口的可视区域内。这样的实现可以提升用户体验,使应用更加友好和易用。
原文地址:https://blog.csdn.net/weixin_71329368/article/details/140214031
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!