class ContextMenuService {
/**
* 容器Dom对象
*
* @private
* @memberof ContextMenuService
*/
private container: Element | undefined;
/**
* Creates an instance of ContextMenuService.
* @memberof ContextMenuService
*/
constructor() {
document.addEventListener('click', () => {
this.clearContainer();
});
}
/**
* 设置容器
*
* @param {Element} container
* @memberof ContextMenuService
*/
setContainer(container: Element) {
if (container) {
this.clearContainer();
this.container = container;
} else {
console.error('容器Dom节点不存在');
}
}
/**
* 清楚容器
*
* @memberof ContextMenuService
*/
clearContainer() {
if (this.container) {
this.container.remove();
}
}
}
const service = new ContextMenuService();
import { Vue, Component, Prop, Emit } from 'vue-property-decorator';
import './context-menu.less';
@Component({})
export class ContextMenu extends Vue {
/**
* 设置右键菜单Class
*
* @type {string}
* @memberof ContextMenu
*/
@Prop()
contextMenuClass?: string;
/**
* 设置右键菜单Style
*
* @type {*}
* @memberof ContextMenu
*/
@Prop()
contextMenuStyle?: any;
/**
* 右键菜单数据,在调用renderContent时会传回去。
*
* @type {*}
* @memberof ContextMenu
*/
@Prop()
data?: any;
/**
* 用于绘制右键菜单内容
*
* @type {any}
* @memberof ContextMenu
*/
@Prop()
renderContent?: any;
/**
* 菜单数据
*
* @type {any[]}
* @memberof ContextMenu
*/
@Prop()
menus?: any[];
/**
* 是否阻止默认绘制上下文菜单
*
* @type {any}
* @memberof ContextMenu
*/
@Prop({ default: false })
isBlocked?: any;
/**
* 显示右键菜单
*
* @param {*} x x轴坐标
* @param {*} y y轴坐标
*/
showContextMenu(x: number, y: number) {
// 创建全屏覆盖容器
const container = document.createElement('div');
service.setContainer(container);
container.oncontextmenu = () => {
container.remove();
};
document.body.appendChild(container);
// 创建Vue实例挂载
const mount = document.createElement('div');
container.appendChild(mount);
let cssClass: string = "";
if (y > window.innerHeight * 0.7) {
cssClass = "context-menus-bottom"
}
this.renderContextMenu(
{
top: y + 'px',
left: x + 'px',
},
mount,
container,
cssClass
);
}
/**
* 绘制菜单
*
* @param {*} position 菜单显示位置
* @param {*} mount Vue实例挂载
* @param {*} container 容器
* @returns
*/
renderContextMenu(position: any, mount: any, container: any,cssClass: string) {
const self = this;
new Vue({
data() {
return {
menus: self.menus,
};
},
methods: {
destroy($event: Event) {
container.remove();
this.$destroy();
$event.stopPropagation();
},
onContextMenu($event: any) {
$event.preventDefault();
},
renderContent() {
let menus;
if (this.menus) {
menus = this.menus.map(item => {
let icon;
if (item.icon) {
icon = ;
}
if (item.iconcls) {
icon = ;
}
return (