mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat(use): add useClickAway
This commit is contained in:
parent
a58da5570b
commit
195f3ffea1
@ -1,2 +1,3 @@
|
|||||||
export { useToggle } from './useToggle';
|
export { useToggle } from './useToggle';
|
||||||
|
export { useClickAway } from './useClickAway';
|
||||||
export { useEventListener } from './useEventListener';
|
export { useEventListener } from './useEventListener';
|
||||||
|
27
packages/vant-use/src/useClickAway/index.ts
Normal file
27
packages/vant-use/src/useClickAway/index.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { Ref, unref } from 'vue';
|
||||||
|
import { inBrowser, useEventListener } from '../useEventListener';
|
||||||
|
|
||||||
|
export type UseClickAwayOptions = {
|
||||||
|
eventName?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useClickAway(
|
||||||
|
target: Element | Ref<Element>,
|
||||||
|
listener: EventListener,
|
||||||
|
options: UseClickAwayOptions = {}
|
||||||
|
) {
|
||||||
|
if (!inBrowser) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { eventName = 'click' } = options;
|
||||||
|
|
||||||
|
const onClick = (event: Event) => {
|
||||||
|
const element = unref(target);
|
||||||
|
if (!element.contains(event.target as Node)) {
|
||||||
|
listener(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEventListener(eventName, onClick, { target: document });
|
||||||
|
}
|
@ -7,7 +7,7 @@ import {
|
|||||||
onDeactivated,
|
onDeactivated,
|
||||||
} from 'vue';
|
} from 'vue';
|
||||||
|
|
||||||
const inBrowser = typeof window !== 'undefined';
|
export const inBrowser = typeof window !== 'undefined';
|
||||||
|
|
||||||
let supportsPassive = false;
|
let supportsPassive = false;
|
||||||
if (inBrowser) {
|
if (inBrowser) {
|
||||||
@ -32,7 +32,7 @@ export type UseEventListenerOptions = {
|
|||||||
export function useEventListener(
|
export function useEventListener(
|
||||||
type: string,
|
type: string,
|
||||||
listener: EventListener,
|
listener: EventListener,
|
||||||
options: UseEventListenerOptions
|
options: UseEventListenerOptions = {}
|
||||||
) {
|
) {
|
||||||
if (!inBrowser) {
|
if (!inBrowser) {
|
||||||
return;
|
return;
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
import { Ref } from 'vue';
|
|
||||||
import { useGlobalEvent } from './use-global-event';
|
|
||||||
|
|
||||||
export type UseClickOutsideOpitons = {
|
|
||||||
event: string;
|
|
||||||
callback: EventListener;
|
|
||||||
element: Ref<Element>;
|
|
||||||
flag?: Ref<boolean>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useClickOutside(options: UseClickOutsideOpitons) {
|
|
||||||
const { event = 'click', callback, element, flag } = options;
|
|
||||||
|
|
||||||
function onClick(event: Event) {
|
|
||||||
if (!element.value.contains(event.target as Node)) {
|
|
||||||
callback(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useGlobalEvent(document, event, onClick, false, flag);
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
import { on, off } from '../utils/dom/event';
|
|
||||||
import {
|
|
||||||
Ref,
|
|
||||||
unref,
|
|
||||||
watch,
|
|
||||||
onMounted,
|
|
||||||
onActivated,
|
|
||||||
onUnmounted,
|
|
||||||
onDeactivated,
|
|
||||||
} from 'vue';
|
|
||||||
|
|
||||||
export function useGlobalEvent(
|
|
||||||
target: EventTarget | Ref<EventTarget>,
|
|
||||||
event: string,
|
|
||||||
handler: EventListener,
|
|
||||||
passive = false,
|
|
||||||
flag?: Ref<boolean>
|
|
||||||
) {
|
|
||||||
let binded: boolean;
|
|
||||||
|
|
||||||
const add = () => {
|
|
||||||
const element = unref(target);
|
|
||||||
|
|
||||||
if (binded || (flag && !flag.value) || !element) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
on(element, event, handler, passive);
|
|
||||||
binded = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const remove = () => {
|
|
||||||
const element = unref(target);
|
|
||||||
if (binded && element) {
|
|
||||||
off(element, event, handler);
|
|
||||||
binded = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (flag) {
|
|
||||||
watch(flag, () => {
|
|
||||||
flag.value ? add() : remove();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(add);
|
|
||||||
onActivated(add);
|
|
||||||
onUnmounted(remove);
|
|
||||||
onDeactivated(remove);
|
|
||||||
}
|
|
@ -4,10 +4,9 @@ import { ref, provide, reactive, computed } from 'vue';
|
|||||||
import { createNamespace, isDef } from '../utils';
|
import { createNamespace, isDef } from '../utils';
|
||||||
|
|
||||||
// Composition
|
// Composition
|
||||||
import { useEventListener } from '@vant/use';
|
import { useClickAway, useEventListener } from '@vant/use';
|
||||||
import { useRect } from '../composition/use-rect';
|
import { useRect } from '../composition/use-rect';
|
||||||
import { useScroller } from '../composition/use-scroller';
|
import { useScroller } from '../composition/use-scroller';
|
||||||
import { useClickOutside } from '../composition/use-click-outside';
|
|
||||||
|
|
||||||
const [createComponent, bem] = createNamespace('dropdown-menu');
|
const [createComponent, bem] = createNamespace('dropdown-menu');
|
||||||
|
|
||||||
@ -55,7 +54,7 @@ export default createComponent({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const onClickOutside = () => {
|
const onClickAway = () => {
|
||||||
children.forEach((item) => {
|
children.forEach((item) => {
|
||||||
item.toggle(false);
|
item.toggle(false);
|
||||||
});
|
});
|
||||||
@ -122,10 +121,7 @@ export default createComponent({
|
|||||||
|
|
||||||
provide(DROPDOWN_KEY, { props, offset, children });
|
provide(DROPDOWN_KEY, { props, offset, children });
|
||||||
|
|
||||||
useClickOutside({
|
useClickAway(rootRef, onClickAway);
|
||||||
element: rootRef,
|
|
||||||
callback: onClickOutside,
|
|
||||||
});
|
|
||||||
|
|
||||||
useEventListener('scroll', onScroll, { target: scroller });
|
useEventListener('scroll', onScroll, { target: scroller });
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { ref, watch, computed, Teleport, Transition } from 'vue';
|
import { ref, watch, computed, Teleport, Transition } from 'vue';
|
||||||
import { createNamespace } from '../utils';
|
import { createNamespace } from '../utils';
|
||||||
import { stopPropagation } from '../utils/dom/event';
|
import { stopPropagation } from '../utils/dom/event';
|
||||||
import { useClickOutside } from '../composition/use-click-outside';
|
import { useClickAway } from '@vant/use';
|
||||||
import Key from './Key';
|
import Key from './Key';
|
||||||
|
|
||||||
const [createComponent, bem] = createNamespace('number-keyboard');
|
const [createComponent, bem] = createNamespace('number-keyboard');
|
||||||
@ -224,11 +224,7 @@ export default createComponent({
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
useClickOutside({
|
useClickAway(rootRef, onClose, { eventName: 'touchstart' });
|
||||||
event: 'touchstart',
|
|
||||||
element: rootRef,
|
|
||||||
callback: onClose,
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const Title = renderTitle();
|
const Title = renderTitle();
|
||||||
|
@ -7,10 +7,10 @@ import { preventDefault } from '../utils/dom/event';
|
|||||||
import { callInterceptor } from '../utils/interceptor';
|
import { callInterceptor } from '../utils/interceptor';
|
||||||
|
|
||||||
// Composition
|
// Composition
|
||||||
|
import { useClickAway } from '@vant/use';
|
||||||
import { useRect } from '../composition/use-rect';
|
import { useRect } from '../composition/use-rect';
|
||||||
import { useTouch } from '../composition/use-touch';
|
import { useTouch } from '../composition/use-touch';
|
||||||
import { usePublicApi } from '../composition/use-public-api';
|
import { usePublicApi } from '../composition/use-public-api';
|
||||||
import { useClickOutside } from '../composition/use-click-outside';
|
|
||||||
|
|
||||||
const [createComponent, bem] = createNamespace('swipe-cell');
|
const [createComponent, bem] = createNamespace('swipe-cell');
|
||||||
|
|
||||||
@ -183,11 +183,7 @@ export default createComponent({
|
|||||||
close,
|
close,
|
||||||
});
|
});
|
||||||
|
|
||||||
useClickOutside({
|
useClickAway(rootRef, onClick, { eventName: 'touchstart' });
|
||||||
element: rootRef,
|
|
||||||
event: 'touchstart',
|
|
||||||
callback: onClick,
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const wrapperStyle = {
|
const wrapperStyle = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user