12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- <template>
- <div :style="style" v-show="show" @mousedown.stop @contextmenu.prevent>
- <slot></slot>
- </div>
- </template>
- <script setup>
- const props = defineProps({
- target: null,
- show: Boolean
- })
- const x = ref(null)
- const y = ref(null)
- const style = ref({})
- const binded = ref(false)
- const emit = defineEmits(['update:show', 'get-context-menu'])
- // 监听show的变化
- watch(
- () => props.show,
- (newValue) => {
- newValue ? bindHideEvents() : unbindHideEvents()
- }
- )
- watch(
- () => props.target,
- (newValue) => {
- bindEvents()
- }
- )
- // 初始化事件
- const bindEvents = (e) => {
- nextTick(() => {
- if (!props.target || binded.value) return
- props.target.addEventListener('contextmenu', contextMenuHandler)
- binded.value = true
- })
- }
- // 绑定隐藏菜单事件
- const bindHideEvents = () => {
- document.addEventListener('mousedown', clickDocumentHandler)
- document.addEventListener('mousewheel', clickDocumentHandler)
- }
- // 取消绑定隐藏菜单事件
- const unbindHideEvents = () => {
- document.removeEventListener('mousedown', clickDocumentHandler)
- document.removeEventListener('mousewheel', clickDocumentHandler)
- }
- // 鼠标按压事件处理器
- const clickDocumentHandler = () => {
- emit('update:show', false)
- }
- // 右键事件事件处理
- const contextMenuHandler = (e) => {
- x.value = e.clientX
- y.value = e.clientY
- layout()
- emit('update:show', true)
- emit('get-context-menu', e)
- e.preventDefault()
- }
- // 布局
- const layout = () => {
- style.value = {
- left: x.value + 'px',
- top: y.value + 'px',
- display: 'block'
- }
- }
- // 取消绑定事件
- const unbindEvents = () => {
- if (!props.target) return
- props.target.removeEventListener('contextmenu', contextMenuHandler)
- }
- </script>
|