mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
chore: adjust useLockScroll、useLazyRender
This commit is contained in:
parent
708c37c759
commit
a4743fa648
@ -41,7 +41,7 @@ export default createComponent({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const show = ref(expanded.value);
|
const show = ref(expanded.value);
|
||||||
const shouldRender = useLazyRender(show);
|
const lazyRender = useLazyRender(show);
|
||||||
|
|
||||||
const onTransitionEnd = () => {
|
const onTransitionEnd = () => {
|
||||||
if (!expanded.value) {
|
if (!expanded.value) {
|
||||||
@ -115,9 +115,7 @@ export default createComponent({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderContent = () => {
|
const renderContent = lazyRender(() => (
|
||||||
if (shouldRender.value) {
|
|
||||||
return (
|
|
||||||
<div
|
<div
|
||||||
ref={wrapperRef}
|
ref={wrapperRef}
|
||||||
vShow={show.value}
|
vShow={show.value}
|
||||||
@ -128,9 +126,7 @@ export default createComponent({
|
|||||||
{slots.default?.()}
|
{slots.default?.()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
));
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<div class={[bem({ border: index.value && props.border })]}>
|
<div class={[bem({ border: index.value && props.border })]}>
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
import { ref, isRef, watch, WatchSource } from 'vue';
|
import { ref, watch, WatchSource, VNode } from 'vue';
|
||||||
|
|
||||||
export function useLazyRender(show: WatchSource<boolean>) {
|
export function useLazyRender(show: WatchSource<boolean>) {
|
||||||
const inited = ref(isRef(show) ? show.value : show());
|
const inited = ref(false);
|
||||||
|
|
||||||
watch(show, (value) => {
|
watch(
|
||||||
|
show,
|
||||||
|
(value) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
inited.value = value;
|
inited.value = value;
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
return inited;
|
return (render: () => VNode) => () => (inited.value ? render() : null);
|
||||||
}
|
}
|
||||||
|
@ -1,55 +1,25 @@
|
|||||||
import { useTouch } from './use-touch';
|
|
||||||
import { getScroller } from '../utils/dom/scroll';
|
|
||||||
import { on, off, preventDefault } from '../utils/dom/event';
|
|
||||||
|
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
const CLASSNAME = 'van-overflow-hidden';
|
const CLASSNAME = 'van-overflow-hidden';
|
||||||
|
|
||||||
export function useLockScroll(element: HTMLElement) {
|
export function useLockScroll(shouldLock: () => boolean) {
|
||||||
const { start, move, deltaY, direction } = useTouch();
|
|
||||||
|
|
||||||
const onTouchMove = ((event: TouchEvent) => {
|
|
||||||
move(event);
|
|
||||||
|
|
||||||
if (direction.value !== 'vertical') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let prevent = false;
|
|
||||||
const up = deltaY.value < 0;
|
|
||||||
const scroller = getScroller(event.target as HTMLElement, element);
|
|
||||||
const { scrollTop, scrollHeight, offsetHeight } = scroller as HTMLElement;
|
|
||||||
|
|
||||||
if (scrollTop === 0) {
|
|
||||||
prevent = up && offsetHeight < scrollHeight;
|
|
||||||
} else if (scrollTop + offsetHeight >= scrollHeight) {
|
|
||||||
prevent = !up;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prevent) {
|
|
||||||
preventDefault(event, true);
|
|
||||||
}
|
|
||||||
}) as EventListener;
|
|
||||||
|
|
||||||
const lock = () => {
|
const lock = () => {
|
||||||
|
if (shouldLock()) {
|
||||||
if (!count) {
|
if (!count) {
|
||||||
document.body.classList.add(CLASSNAME);
|
document.body.classList.add(CLASSNAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
on(document, 'touchstart', start);
|
}
|
||||||
on(document, 'touchmove', onTouchMove);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
lock();
|
const unlock = () => {
|
||||||
|
if (shouldLock() && count) {
|
||||||
return function unlock() {
|
|
||||||
count--;
|
count--;
|
||||||
off(document, 'touchstart', start);
|
|
||||||
off(document, 'touchmove', onTouchMove);
|
|
||||||
|
|
||||||
if (!count) {
|
if (!count) {
|
||||||
document.body.classList.remove(CLASSNAME);
|
document.body.classList.remove(CLASSNAME);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return [lock, unlock];
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import {
|
|||||||
ref,
|
ref,
|
||||||
watch,
|
watch,
|
||||||
Teleport,
|
Teleport,
|
||||||
|
computed,
|
||||||
onMounted,
|
onMounted,
|
||||||
Transition,
|
Transition,
|
||||||
onActivated,
|
onActivated,
|
||||||
@ -12,6 +13,7 @@ import {
|
|||||||
import { createNamespace, isDef } from '../utils';
|
import { createNamespace, isDef } from '../utils';
|
||||||
|
|
||||||
// Composition
|
// Composition
|
||||||
|
import { useLockScroll } from '../composition/use-lock-scroll';
|
||||||
import { useLazyRender } from '../composition/use-lazy-render';
|
import { useLazyRender } from '../composition/use-lazy-render';
|
||||||
import { CloseOnPopstateMixin } from '../mixins/close-on-popstate';
|
import { CloseOnPopstateMixin } from '../mixins/close-on-popstate';
|
||||||
|
|
||||||
@ -106,32 +108,28 @@ export default createComponent({
|
|||||||
|
|
||||||
const zIndex = ref();
|
const zIndex = ref();
|
||||||
|
|
||||||
const shouldRender = useLazyRender(() => props.show || !props.lazyRender);
|
const [lockScroll, unlockScroll] = useLockScroll(() => props.lockScroll);
|
||||||
|
|
||||||
const lockScroll = () => {
|
const lazyRender = useLazyRender(() => props.show || !props.lazyRender);
|
||||||
if (props.lockScroll) {
|
|
||||||
if (!context.lockCount) {
|
const style = computed(() => {
|
||||||
document.body.classList.add('van-overflow-hidden');
|
const style = {
|
||||||
}
|
zIndex: zIndex.value,
|
||||||
context.lockCount++;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const unlockScroll = () => {
|
if (isDef(props.duration)) {
|
||||||
if (props.lockScroll && context.lockCount) {
|
const key =
|
||||||
context.lockCount--;
|
props.position === 'center'
|
||||||
|
? 'animationDuration'
|
||||||
|
: 'transitionDuration';
|
||||||
|
style[key] = `${props.duration}s`;
|
||||||
|
}
|
||||||
|
|
||||||
if (!context.lockCount) {
|
return style;
|
||||||
document.body.classList.remove('van-overflow-hidden');
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const open = () => {
|
const open = () => {
|
||||||
if (opened) {
|
if (!opened) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.zIndex !== undefined) {
|
if (props.zIndex !== undefined) {
|
||||||
context.zIndex = props.zIndex;
|
context.zIndex = props.zIndex;
|
||||||
}
|
}
|
||||||
@ -139,6 +137,7 @@ export default createComponent({
|
|||||||
opened = true;
|
opened = true;
|
||||||
lockScroll();
|
lockScroll();
|
||||||
zIndex.value = ++context.zIndex;
|
zIndex.value = ++context.zIndex;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const close = () => {
|
const close = () => {
|
||||||
@ -151,7 +150,6 @@ export default createComponent({
|
|||||||
|
|
||||||
const onClickOverlay = () => {
|
const onClickOverlay = () => {
|
||||||
emit('click-overlay');
|
emit('click-overlay');
|
||||||
|
|
||||||
if (props.closeOnClickOverlay) {
|
if (props.closeOnClickOverlay) {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
@ -190,38 +188,12 @@ export default createComponent({
|
|||||||
const onOpened = () => emit('opened');
|
const onOpened = () => emit('opened');
|
||||||
const onClosed = () => emit('closed');
|
const onClosed = () => emit('closed');
|
||||||
|
|
||||||
const renderPopup = () => {
|
const renderPopup = lazyRender(() => {
|
||||||
const {
|
const { round, position, safeAreaInsetBottom } = props;
|
||||||
round,
|
|
||||||
position,
|
|
||||||
duration,
|
|
||||||
transition,
|
|
||||||
safeAreaInsetBottom,
|
|
||||||
} = props;
|
|
||||||
const isCenter = position === 'center';
|
|
||||||
|
|
||||||
const transitionName =
|
|
||||||
transition || (isCenter ? 'van-fade' : `van-popup-slide-${position}`);
|
|
||||||
|
|
||||||
const style = {
|
|
||||||
zIndex: zIndex.value,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (isDef(duration)) {
|
|
||||||
const key = isCenter ? 'animationDuration' : 'transitionDuration';
|
|
||||||
style[key] = `${duration}s`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Transition
|
|
||||||
name={transitionName}
|
|
||||||
onAfterEnter={onOpened}
|
|
||||||
onAfterLeave={onClosed}
|
|
||||||
>
|
|
||||||
{shouldRender.value ? (
|
|
||||||
<div
|
<div
|
||||||
vShow={props.show}
|
vShow={props.show}
|
||||||
style={style}
|
style={style.value}
|
||||||
class={bem({
|
class={bem({
|
||||||
round,
|
round,
|
||||||
[position]: position,
|
[position]: position,
|
||||||
@ -233,7 +205,21 @@ export default createComponent({
|
|||||||
{slots.default?.()}
|
{slots.default?.()}
|
||||||
{renderCloseIcon()}
|
{renderCloseIcon()}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const renderTransition = () => {
|
||||||
|
const { position, transition } = props;
|
||||||
|
const name =
|
||||||
|
position === 'center' ? 'van-fade' : `van-popup-slide-${position}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Transition
|
||||||
|
name={transition || name}
|
||||||
|
onAfterEnter={onOpened}
|
||||||
|
onAfterLeave={onClosed}
|
||||||
|
>
|
||||||
|
{renderPopup()}
|
||||||
</Transition>
|
</Transition>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -282,7 +268,7 @@ export default createComponent({
|
|||||||
return (
|
return (
|
||||||
<Teleport to={props.teleport}>
|
<Teleport to={props.teleport}>
|
||||||
{renderOverlay()}
|
{renderOverlay()}
|
||||||
{renderPopup()}
|
{renderTransition()}
|
||||||
</Teleport>
|
</Teleport>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -290,7 +276,7 @@ export default createComponent({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{renderOverlay()}
|
{renderOverlay()}
|
||||||
{renderPopup()}
|
{renderTransition()}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user