学习关键语句:
vue自定义右键菜单
js右键菜单
写在前面
所以在逛UI库 (Naive UI) 的时候 , 学习到下拉菜单时发现可以在区域部分定制个人的右键菜单栏 , 打开组件代码看了看 , 真想马上就学习起来 , 接下来 , 我们一起来尝试做一个最简单的自定义右键菜单
编码思路
额 , 如何去完成一个自定义右键菜单呢 ? 老实说一开始我完全没有想法 , 人都麻了 , 再又一次仔细看了看组件库代码后 , 有了一点点头绪
我们需要达成的目标如下:
- 需要一个元素做为右键菜单的上级
- 点击右键时不能出现浏览器默认右键菜单(例如出现:检查元素等)
- 菜单栏需要出现在你想出现的地方(鼠标右键单击处)
- 同时菜单栏需要关闭在你任何想关闭的时候(鼠标点击任意处)
那么我们现在就开始
这里使用普通 html 文件在线引入 vue2 的方式进行编写
文章末尾附带本文项目文件
开始
1.完成基本内容编写
基本内容包括什么 ? 既然是最简单的自定义菜单 , 那么就只需要最简单的三个元素
分别是:目标点击区域元素 、菜单栏元素、遮罩层
搭建基本框架
粉色方块是右键菜单存在的区域,菜单栏随便给个数字,为了展示放了一个文本信息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.min.js"></script>
<title>自定义右键菜单</title>
</head>
<body>
<div id="app">
<div class="box"></div>
<p style="font-size:40px">{{ txt }}</p>
<div class="shade"></div>
<div class="list">
<div class="item" v-for="(item, index) in 5" :key="index" >
{{ item }}
</div>
</div>
</div>
</body>
</html>
<script>
let vm = new Vue({
el: "#app",
data: {
txt: '在粉色区域右键单击打开菜单'
}
})
</script>
<style>
* {
margin: 0;
padding: 0;
}
.box {
width: 300px;
height: 300px;
background-color: pink;
}
.shade {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 998;
background: transparent;
}
.list {
width: 100px;
background-color: white;
display: flex;
flex-direction: column;
align-items: center;
position: absolute;
top: 0;
left: 0;
z-index: 999;
}
.item {
width: 98%;
height: 30px;
line-height: 30px;
text-align: center;
color: black;
background-color: #eee;
margin: 0.5px 0;
cursor: pointer;
}
.item:hover {
color: white;
background-color: rgb(43, 124, 238);
}
</style>
打开如下图所示
同时注意,为了节省文章长度,接下来的代码块内容将省略样式表内容,声明:样式表内容未发生任何改变,从始至终都是上面这样
2.理清逻辑
比敲代码更重要的是理清逻辑,清晰的逻辑可以节约大量的精力
基本逻辑:
开始 ▶ 右键点击粉色方块 ▶ 菜单栏和遮罩层出现 ▶ 菜单栏可见菜单选项,遮罩层透明可看见后面元素 ▶ 菜单栏层级最高,遮罩层层级仅次于菜单栏 ▶ 点击菜单栏触发选中菜单事件或遮罩层无事件后菜单栏和遮罩层都消失 ▶ 完成
你可能有不会的问题(实际上是我做的时候不会的问题):
Q:如何防止右键出现浏览器默认菜单?
A:在元素中添加属性方法 @contextmenu="$event.preventDefault()" 就可以阻止默认行为
<div class="box" @contextmenu="$event.preventDefault()"></div>
Q:怎么让菜单出现在鼠标点击的位置呢?
A:通过获取鼠标点击位置的横纵坐标(x,y)来设置菜单栏的位置(x = clientX ,y = clientY),只需要将菜单栏设置为绝对定位,就可以通过 top 和 left 属性设置样式
<div class="box" @contextmenu="handleMenu"></div>
<script>
let vm = new Vue({
el: "#app",
data: {
listVisible: false,
x: 0,
y: 0,
txt: '在粉色区域右键单击打开菜单'
},
methods: {
handleMenu(e) {
e.preventDefault()
this.listVisible = true
this.x = e.clientX
this.y = e.clientY
}
}
})
</script>
3.完成所有内容
基本逻辑已经搞清楚了,一些难点我们也已经解决了,所有如果有哪位有意向于前端开发的朋友阅读到这里 , 就可以尝试自己动手完成接下来的工作了
一些小的细节地方不再进行讲解
<body>
<div id="app">
<div class="box" @contextmenu="handleMenu"></div>
<p style="font-size:40px">{{ txt }}</p>
<div
v-show="listVisible"
class="shade"
@click="listVisible = false"
@contextmenu="handleShade"
></div>
<div
v-show="listVisible"
class="list"
:style="{left:x + 'px',top:y + 'px'}"
@contextmenu="$event.preventDefault()"
>
<div
class="item"
v-for="(item, index) in 5"
:key="index"
@click="handleItem(item)"
@contextmenu="$event.preventDefault()"
>
{{ item }}
</div>
</div>
</div>
</body>
</html>
<script>
let vm = new Vue({
el: "#app",
data: {
listVisible: false,
x: 0,
y: 0,
txt: '在粉色区域右键单击打开菜单'
},
methods: {
handleMenu(e) {
e.preventDefault()
this.listVisible = true
this.x = e.clientX
this.y = e.clientY
},
handleShade(e) {
e.preventDefault()
this.listVisible = false
},
handleItem(item) {
this.listVisible = false
this.txt = `点击了菜单 ${item} !`
}
}
})
</script>
结束
如此一来,一个非常简单的但是又十分有用的自定义菜单就完成了
(ps:组件的相关制作不会写成文章发布,请不用等待,vue3版的过几个月会发布文章,建议直接自己上vue3,说实话好久没用 this 今天报了好几次错误)