实现右键菜单
功能需求
在前面的基础上,我们进一步增加业务功能,使其用起来更方便。
具体来说,就是为事件(对应任务)增加右键菜单,能便捷的进行操作,如复制任务、删除任务、添加工时等。
先翻找官方文档,日历组件并没有预置右键菜单扩展,也没有相关说明,需要自行摸索实现。
实现思路1——使用插槽
使用eventContent插槽,自行用div包起来,然后在div上添加@contextmenu事件,如下所示:
<div>
<FullCalendar :options="calendarOptions" ref="fullCalendar">
<template #eventContent="arg">
<div @contextmenu="contextmenu"> {{ arg.event.title }} </div>
</template>
</FullCalendar>
</div>
contextmenu(e) {
e.preventDefault()
console.log(e)
}
上述方式可以显示事件的名称,但右键菜单的处理无效,浏览器的右键菜单还是会弹出来,推测组件又做了啥内部处理和封装导致的,contextmenu根本不会被调用。
在外侧放了一个div标签挂载了contextmenu做对比验证,发现能正常运行,基本确定是日历组件内部处理导致的。
<div>
<div @contextmenu="contextmenu"> 测试 </div>
<FullCalendar :options="calendarOptions" ref="fullCalendar">
<template #eventContent="arg">
<div @contextmenu="contextmenu"> {{ arg.event.title }} </div>
</template>
</FullCalendar>
</div>
因此,此路走不通。
此外,即使右键菜单能生效,该方案还存在一个问题,就是需要自己覆写日历组件的内容展现部分,意味着官方原先一些预置的属性和功能,如是否显示事件的起止时间、颜色和背景的控制等,将失去作用,因此,强烈不建议采用此思路。
实现思路2——使用回调
组件预置了一个事件加载完成后的回调事件,我们可以在这个环节添加一个右键监听,然后阻止浏览器默认右键菜单,并调用自己的右键菜单。
// 事件加载完成
eventDidMount(arg) {
//添加右键菜单
arg.el.addEventListener('contextmenu', (e) => {
//阻止浏览器的默认右键菜单
e.preventDefault()
this.showEventContextMenu(e, arg.event.id)
})
}
调用右键菜单如下:
// 显示事件右键菜单
showEventContextMenu(mouseEvent, eventId) {
// 保存当前事件标识
this.contextMenuEventId = eventId
// 显示右键菜单
this.$nextTick(() => {
this.eventContextMenu.left = mouseEvent.clientX - 10
const menuHeight = this.$refs.eventContextMenu.$el.clientHeight
const areaHeight = document.documentElement.clientHeight
if (mouseEvent.clientY + menuHeight > areaHeight) {
// 当鼠标点击的y坐标加上菜单高度超出区域高度时
this.eventContextMenu.top = mouseEvent.clientY - menuHeight + 25
} else {
this.eventContextMenu.top = mouseEvent.clientY - 25
}
// 显示菜单
this.eventContextMenu.visible = true
})
}
相应的右键菜单使用element-plus的菜单控件,如下:
<el-menu
v-show="eventContextMenu.visible"
ref="eventContextMenu"
:style="{
width: '120px',
left: eventContextMenu.left + 'px',
top: eventContextMenu.top + 'px',
position: 'fixed',
cursor: 'pointer',
'z-index': 9999
}"
popper-append-to-body
@mouseleave="eventContextMenu.visible = false"
@select="eventContextMenuSelect"
>
<el-menu-item index="addLog">
<el-icon>
<CloseBold />
</el-icon>
<span>记录用时</span></el-menu-item
>
<el-menu-item index="copy">
<el-icon>
<CopyDocument />
</el-icon>
<span>复制任务</span></el-menu-item
>
<el-menu-item index="remove">
<el-icon>
<FolderRemove />
</el-icon>
<span>删除任务</span></el-menu-item
>
</el-menu>
这个过程中需要一些属性来保存和传递数据,如下:
// 当前右键菜单事件标识
contextMenuEventId: '',
// 事件右键菜单属性
eventContextMenu: {
// 是否可见
visible: false,
// 左边距
left: 0,
// 上边距
top: 0
}
效果如下:
应用系统
名称:遇见
地址:https://meet.popsoft.tech
说明:基于一二三应用开发平台和FullCalendar日历组件实现的面向个人的时间管理、任务管理系统,1分钟注册,完整功能,欢迎使用~