chore(Sticky): improve code (#8045)

This commit is contained in:
neverland 2021-01-31 17:01:01 +08:00 committed by GitHub
parent 6c5315f0b1
commit 0d7ff429d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 32 deletions

View File

@ -4,7 +4,7 @@ import { computed, CSSProperties, PropType, reactive, ref } from 'vue';
import { createNamespace, getScrollTop, isHidden, unitToPx } from '../utils'; import { createNamespace, getScrollTop, isHidden, unitToPx } from '../utils';
// Composition // Composition
import { useEventListener, useScrollParent } from '@vant/use'; import { useRect, useEventListener, useScrollParent } from '@vant/use';
import { useVisibilityChange } from '../composables/use-visibility-change'; import { useVisibilityChange } from '../composables/use-visibility-change';
const [createComponent, bem] = createNamespace('sticky'); const [createComponent, bem] = createNamespace('sticky');
@ -37,9 +37,8 @@ export default createComponent({
const state = reactive({ const state = reactive({
fixed: false, fixed: false,
height: 0, // root 高度 width: 0, // root width
width: 0, // root 宽度 height: 0, // root height
clientHeight: 0, // documentElement clientHeight
transform: 0, transform: 0,
}); });
@ -51,20 +50,26 @@ export default createComponent({
return; return;
} }
const top = offsetTop.value ? `${offsetTop.value}px` : 0; const style: CSSProperties = {
const bottom = offsetBottom.value ? `${offsetBottom.value}px` : 0;
const transform = state.transform
? `translate3d(0, ${state.transform}px, 0)`
: undefined;
return {
height: `${state.height}px`,
width: `${state.width}px`, width: `${state.width}px`,
top: props.position === 'top' ? top : undefined, height: `${state.height}px`,
bottom: props.position === 'bottom' ? bottom : undefined,
zIndex: props.zIndex !== undefined ? +props.zIndex : undefined,
transform,
}; };
if (state.transform) {
style.transform = `translate3d(0, ${state.transform}px, 0)`;
}
if (props.zIndex !== undefined) {
style.zIndex = +props.zIndex;
}
if (props.position === 'top') {
style.top = offsetTop.value ? `${offsetTop.value}px` : 0;
} else {
style.bottom = offsetBottom.value ? `${offsetBottom.value}px` : 0;
}
return style;
}); });
const emitScrollEvent = (scrollTop: number) => { const emitScrollEvent = (scrollTop: number) => {
@ -80,17 +85,16 @@ export default createComponent({
} }
const { container } = props; const { container } = props;
const rootRect = root.value.getBoundingClientRect(); const rootRect = useRect(root);
const containerRect = container?.getBoundingClientRect(); const containerRect = container?.getBoundingClientRect();
state.height = rootRect.height;
state.width = rootRect.width; state.width = rootRect.width;
state.clientHeight = document.documentElement.clientHeight; state.height = rootRect.height;
const scrollTop = getScrollTop(window); const scrollTop = getScrollTop(window);
// The sticky component should be kept inside the container element
if (props.position === 'top') { if (props.position === 'top') {
// The sticky component should be kept inside the container element
if (container) { if (container) {
const difference = const difference =
containerRect.bottom - offsetTop.value - state.height; containerRect.bottom - offsetTop.value - state.height;
@ -101,19 +105,19 @@ export default createComponent({
state.fixed = offsetTop.value > rootRect.top; state.fixed = offsetTop.value > rootRect.top;
} }
} else if (props.position === 'bottom') { } else if (props.position === 'bottom') {
const { clientHeight } = document.documentElement;
if (container) { if (container) {
const difference = const difference =
state.clientHeight - clientHeight -
containerRect.top - containerRect.top -
offsetBottom.value - offsetBottom.value -
state.height; state.height;
state.fixed = state.fixed =
state.clientHeight - offsetBottom.value < rootRect.bottom && clientHeight - offsetBottom.value < rootRect.bottom &&
state.clientHeight > containerRect.top; clientHeight > containerRect.top;
state.transform = difference < 0 ? -difference : 0; state.transform = difference < 0 ? -difference : 0;
} else { } else {
state.fixed = state.fixed = clientHeight - offsetBottom.value < rootRect.bottom;
state.clientHeight - offsetBottom.value < rootRect.bottom;
} }
} }
emitScrollEvent(scrollTop); emitScrollEvent(scrollTop);
@ -125,8 +129,8 @@ export default createComponent({
return () => { return () => {
const { fixed, height, width } = state; const { fixed, height, width } = state;
const rootStyle: CSSProperties = { const rootStyle: CSSProperties = {
height: fixed ? `${height}px` : undefined,
width: fixed ? `${width}px` : undefined, width: fixed ? `${width}px` : undefined,
height: fixed ? `${height}px` : undefined,
}; };
return ( return (

View File

@ -36,7 +36,7 @@ exports[`should sticky inside container bottom when using container prop 1`] = `
</div> </div>
<div style="height: 44px; width: 88px;"> <div style="height: 44px; width: 88px;">
<div class="van-sticky van-sticky--fixed" <div class="van-sticky van-sticky--fixed"
style="height: 44px; width: 88px; bottom: 0px;" style="width: 88px; height: 44px; bottom: 0px;"
> >
Content Content
</div> </div>
@ -50,7 +50,7 @@ exports[`should sticky inside container bottom when using container prop 2`] = `
</div> </div>
<div style="height: 44px; width: 88px;"> <div style="height: 44px; width: 88px;">
<div class="van-sticky van-sticky--fixed" <div class="van-sticky van-sticky--fixed"
style="height: 44px; width: 88px; bottom: 0px; transform: translate3d(0, 24px, 0);" style="width: 88px; height: 44px; bottom: 0px; transform: translate3d(0, 24px, 0);"
> >
Content Content
</div> </div>
@ -62,7 +62,7 @@ exports[`should sticky inside container when using container prop 1`] = `
<div style="height: 150px;"> <div style="height: 150px;">
<div style="height: 44px; width: 88px;"> <div style="height: 44px; width: 88px;">
<div class="van-sticky van-sticky--fixed" <div class="van-sticky van-sticky--fixed"
style="height: 44px; width: 88px; top: 0px;" style="width: 88px; height: 44px; top: 0px;"
> >
Content Content
</div> </div>
@ -74,7 +74,7 @@ exports[`should sticky inside container when using container prop 2`] = `
<div style="height: 150px;"> <div style="height: 150px;">
<div style="height: 44px; width: 88px;"> <div style="height: 44px; width: 88px;">
<div class="van-sticky van-sticky--fixed" <div class="van-sticky van-sticky--fixed"
style="height: 44px; width: 88px; top: 0px; transform: translate3d(0, -14px, 0);" style="width: 88px; height: 44px; top: 0px; transform: translate3d(0, -14px, 0);"
> >
Content Content
</div> </div>
@ -105,7 +105,7 @@ exports[`should sticky to top after scrolling 1`] = `
exports[`should update z-index when using z-index prop 1`] = ` exports[`should update z-index when using z-index prop 1`] = `
<div style="height: 10px;"> <div style="height: 10px;">
<div class="van-sticky van-sticky--fixed" <div class="van-sticky van-sticky--fixed"
style="top: 0px; z-index: 0;" style="z-index: 0; top: 0px;"
> >
Content Content
</div> </div>