mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
chore(Sticky): improve code (#8045)
This commit is contained in:
parent
6c5315f0b1
commit
0d7ff429d9
@ -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 (
|
||||||
|
@ -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>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user