Skip to content

Commit

Permalink
feat(mouse-menu): add longPressPreventDefault option
Browse files Browse the repository at this point in the history
  • Loading branch information
leon-kfd committed Aug 4, 2023
1 parent a04bbc1 commit 12ea98e
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 16 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ module.exports = {
'vue/html-self-closing': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/ban-ts-comment': 'off'
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-explicit-any': 'off'
}
};
1 change: 1 addition & 0 deletions packages/mouse-menu/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
|disabled|是否禁用整个菜单,接收一个函数|(params: any) => boolean|-|-|
|useLongPressInMobile|移动端下兼容使用长按事件唤出菜单, 但长按模式不支持多级菜单(仅支持指令方式)|Boolean|-|false|
|longPressDuration|长按事件需持续时间,单位ms|Number|-|500|
|longPressPreventDefault|长按事件下touchstart是否PreventDefault, 可接收函数|Boolean/Function|-|
|injectCloseListener|自动注入关闭菜单的Listener,设为false时需自行处理|Boolean|-|true|
|customClass|注入自定义类名到MenuWrapper上|String|-|-|
|onOpen|菜单打开后的回调(^2.0.8)|Function|-|-|
Expand Down
25 changes: 19 additions & 6 deletions packages/mouse-menu/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { App, DirectiveBinding, h, render, ComponentPublicInstance, ObjectDirective } from 'vue';
import { App, DirectiveBinding, createVNode, render, ComponentPublicInstance, ObjectDirective } from 'vue';
import { CustomMouseMenuOptions } from './types';
import MouseMenu from './mouse-menu.vue';
import { createClassDom } from '../shared';
Expand All @@ -15,23 +15,32 @@ function CustomMouseMenu (options: CustomMouseMenuOptions) {
} else {
container = createClassDom('div', className);
}
const vm = h(MouseMenu, options);
const vm = createVNode(MouseMenu, options);
render(vm, container);
document.body.appendChild(container);
return vm.component?.proxy as ComponentPublicInstance<typeof MouseMenu>;
}

type ContextMenuListenFn = (e: MouseEvent) => void
type TouchListenFn = (e: TouchEvent) => void
type PreventCheckFn = (e?: TouchEvent, el?: HTMLElement) => boolean

let MouseMenuCtx: ComponentPublicInstance<typeof MouseMenu>;
let longPressTimer: number;
let longPressTouchStart: TouchListenFn;
let longPressTouchEnd: TouchListenFn;
function addLongPressListener (el: HTMLElement, fn: TouchListenFn, longPressDuration = 500) {
function addLongPressListener (el: HTMLElement, fn: TouchListenFn, longPressDuration = 500, longPressPreventDefault?: PreventCheckFn | boolean) {
longPressTouchStart = (e: TouchEvent) => {
MouseMenuCtx && MouseMenuCtx.close();
e.preventDefault();
if (typeof longPressPreventDefault === 'function') {
if (longPressPreventDefault(e, el)) {
e.preventDefault();
}
} else if (typeof longPressPreventDefault === 'boolean') {
if (longPressPreventDefault) {
e.preventDefault();
}
}
if (longPressTimer) clearTimeout(longPressTimer);
longPressTimer = window.setTimeout(() => {
fn(e);
Expand Down Expand Up @@ -73,7 +82,6 @@ const mounted = (el: HTMLElement, binding: DirectiveBinding) => {
if (value.useLongPressInMobile && 'ontouchstart' in window) {
longPressEvent = (e: TouchEvent) => {
if (typeof value.disabled === 'function' && value.disabled(value.params)) return;
e.preventDefault();
MouseMenuCtx = CustomMouseMenu({
el,
...value
Expand All @@ -89,7 +97,12 @@ const mounted = (el: HTMLElement, binding: DirectiveBinding) => {
}, 500);
};
removeLongPressListener(el);
addLongPressListener(el, longPressEvent, value.longPressDuration || 500);
addLongPressListener(
el,
longPressEvent,
value.longPressDuration || 500,
value.longPressPreventDefault
);
}
} else {
throw new Error('At least set one menu list!');
Expand Down
20 changes: 12 additions & 8 deletions packages/mouse-menu/mouse-menu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
v-if="!item.hidden && !item.line"
:key="index"
:class="['__menu__item', item.disabled && 'disabled', item.customClass]"
@mousedown.stop="handleMenuItemClick(item, $event)"
@[clickEventKey].stop="handleMenuItemClick(item, $event)"
@mouseenter="handleMenuMouseEnter($event,item)"
>
<div v-if="hasIcon" class="__menu__item-icon">
Expand Down Expand Up @@ -45,7 +45,7 @@
v-if="!subItem.hidden && !subItem.line"
:key="subIndex"
:class="['__menu__sub__item', subItem.disabled && 'disabled', subItem.customClass]"
@mousedown.stop="handleSubMenuItemClick(subItem, $event)"
@[clickEventKey].stop="handleSubMenuItemClick(subItem, $event)"
>
<span class="__menu__sub__item-label">{{ subItem.label }}</span>
<span class="__menu__sub__item-tips">{{ subItem.tips || '' }}</span>
Expand Down Expand Up @@ -101,6 +101,7 @@ export default defineComponent({
},
useLongPressInMobile: Boolean,
longPressDuration: Number,
longPressPreventDefault: [Function, Boolean],
injectCloseListener: {
type: Boolean,
default: true
Expand All @@ -119,7 +120,7 @@ export default defineComponent({
const menuLeft = ref(0);
const showMenu = ref(false);
const clickDomEl = ref(null) as Ref<null | HTMLElement>;
const calcMenuList = ref([] as MenuSetting[]);
const calcMenuList = ref([] as Array<MenuSetting & { icon?: any }>);
const hasSubMenu = computed(() => props.menuList.some(item => item.children && item.children.length > 0));
const arrowSize = ref(10);
const MenuWrapper = ref();
Expand Down Expand Up @@ -238,24 +239,26 @@ export default defineComponent({
showMenu.value = false;
};
const clickEventKey = computed(() => props.useLongPressInMobile && 'ontouchstart' in window ? 'touchstart' : 'mousedown')
// injectCloseListener
const listenerFn = (e: MouseEvent) => {
const listenerFn = (e: Event) => {
if (MenuWrapper.value && !MenuWrapper.value.contains(e.currentTarget)) {
showMenu.value = false;
document.oncontextmenu = null;
}
};
watch(() => props.injectCloseListener, (val) => {
if (val) {
document.addEventListener('mousedown', listenerFn);
document.addEventListener(clickEventKey.value, listenerFn);
} else {
document.removeEventListener('mousedown', listenerFn);
document.removeEventListener(clickEventKey.value, listenerFn);
}
}, {
immediate: true
});
onUnmounted(() => {
document.removeEventListener('mousedown', listenerFn);
document.removeEventListener(clickEventKey.value, listenerFn);
});
return {
Expand All @@ -274,7 +277,8 @@ export default defineComponent({
handleSubMenuItemClick,
handleMenuMouseEnter,
show,
close
close,
clickEventKey
};
}
});
Expand Down
8 changes: 7 additions & 1 deletion src/pages/mouse-menu/example/example1.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export default defineComponent({
},
options: {
params: { a: 1 },
useLongPressInMobile: true,
menuList: [
{
label: '打开',
Expand Down Expand Up @@ -59,6 +58,13 @@ export default defineComponent({
// 菜单Close回调
onClose: () => {
console.log('onClose')
},
// 移动端长按配置
useLongPressInMobile: true,
longPressDuration: 300,
longPressPreventDefault: (e: Event, el: HTMLElement) => {
console.log({ e, el })
return false
}
}
};
Expand Down

0 comments on commit 12ea98e

Please sign in to comment.