contextmenu.ts 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. import { Directive, createVNode, render, DirectiveBinding } from 'vue'
  2. import ContextmenuComponent from '@/components/Contextmenu/index.vue'
  3. const CTX_CONTEXTMENU_HANDLER = 'CTX_CONTEXTMENU_HANDLER'
  4. const contextmenuListener = (el: HTMLElement, event: MouseEvent, binding: DirectiveBinding) => {
  5. event.stopPropagation()
  6. event.preventDefault()
  7. const menus = binding.value(el)
  8. if (!menus) return
  9. let container: HTMLDivElement | null = null
  10. const removeContextmenu = () => {
  11. if (container) {
  12. document.body.removeChild(container)
  13. container = null
  14. }
  15. el.classList.remove('contextmenu-active')
  16. document.body.removeEventListener('scroll', removeContextmenu)
  17. window.removeEventListener('resize', removeContextmenu)
  18. }
  19. const options = {
  20. axis: { x: event.x, y: event.y },
  21. el,
  22. menus,
  23. removeContextmenu,
  24. }
  25. container = document.createElement('div')
  26. const vm = createVNode(ContextmenuComponent, options, null)
  27. render(vm, container)
  28. document.body.appendChild(container)
  29. el.classList.add('contextmenu-active')
  30. document.body.addEventListener('scroll', removeContextmenu)
  31. window.addEventListener('resize', removeContextmenu)
  32. }
  33. const ContextmenuDirective: Directive = {
  34. mounted(el: HTMLElement, binding) {
  35. el[CTX_CONTEXTMENU_HANDLER] = (event: MouseEvent) => contextmenuListener(el, event, binding)
  36. el.addEventListener('contextmenu', el[CTX_CONTEXTMENU_HANDLER])
  37. },
  38. unmounted(el: HTMLElement) {
  39. if (el && el[CTX_CONTEXTMENU_HANDLER]) {
  40. el.removeEventListener('contextmenu', el[CTX_CONTEXTMENU_HANDLER])
  41. delete el[CTX_CONTEXTMENU_HANDLER]
  42. }
  43. },
  44. }
  45. export default ContextmenuDirective