feat(Sticky): support sticky to bottom (#7979)

This commit is contained in:
kooriookami
2021-01-31 16:43:49 +08:00
committed by GitHub
parent 0f3610bafe
commit 6c5315f0b1
8 changed files with 314 additions and 67 deletions
@@ -51,4 +51,22 @@ exports[`should render demo and match snapshot 1`] = `
</div>
</div>
</div>
<div>
<div style="height: 200px;">
</div>
<div>
<div class="van-sticky">
<button type="button"
class="van-button van-button--primary van-button--normal"
style="margin-left: 15px;"
>
<div class="van-button__content">
<span class="van-button__text">
Offset Bottom
</span>
</div>
</button>
</div>
</div>
</div>
`;
@@ -30,11 +30,39 @@ exports[`should allow to using offset-top prop with vw unit 1`] = `
</div>
`;
exports[`should sticky inside container when using container prop 1`] = `
<div style="height: 20px;">
<div style="height: 10px;">
exports[`should sticky inside container bottom when using container prop 1`] = `
<div style="margin-top: 640px;">
<div style="height: 150px;">
</div>
<div style="height: 44px; width: 88px;">
<div class="van-sticky van-sticky--fixed"
style="transform: translate3d(0, -5px, 0);"
style="height: 44px; width: 88px; bottom: 0px;"
>
Content
</div>
</div>
</div>
`;
exports[`should sticky inside container bottom when using container prop 2`] = `
<div style="margin-top: 640px;">
<div style="height: 150px;">
</div>
<div style="height: 44px; width: 88px;">
<div class="van-sticky van-sticky--fixed"
style="height: 44px; width: 88px; bottom: 0px; transform: translate3d(0, 24px, 0);"
>
Content
</div>
</div>
</div>
`;
exports[`should sticky inside container when using container prop 1`] = `
<div style="height: 150px;">
<div style="height: 44px; width: 88px;">
<div class="van-sticky van-sticky--fixed"
style="height: 44px; width: 88px; top: 0px;"
>
Content
</div>
@@ -43,26 +71,32 @@ exports[`should sticky inside container when using container prop 1`] = `
`;
exports[`should sticky inside container when using container prop 2`] = `
<div style="height: 20px;">
<div style="height: 10px;">
<div class="van-sticky">
<div style="height: 150px;">
<div style="height: 44px; width: 88px;">
<div class="van-sticky van-sticky--fixed"
style="height: 44px; width: 88px; top: 0px; transform: translate3d(0, -14px, 0);"
>
Content
</div>
</div>
</div>
`;
exports[`should sticky to top after scrolling 1`] = `
exports[`should sticky to bottom after scrolling 1`] = `
<div style="height: 10px;">
<div class="van-sticky">
<div class="van-sticky van-sticky--fixed"
style="bottom: 10px;"
>
Content
</div>
</div>
`;
exports[`should sticky to top after scrolling 2`] = `
exports[`should sticky to top after scrolling 1`] = `
<div style="height: 10px;">
<div class="van-sticky van-sticky--fixed">
<div class="van-sticky van-sticky--fixed"
style="top: 0px;"
>
Content
</div>
</div>
@@ -71,7 +105,7 @@ exports[`should sticky to top after scrolling 2`] = `
exports[`should update z-index when using z-index prop 1`] = `
<div style="height: 10px;">
<div class="van-sticky van-sticky--fixed"
style="z-index: 0;"
style="top: 0px; z-index: 0;"
>
Content
</div>
+162 -14
View File
@@ -1,19 +1,51 @@
import { nextTick, ref } from 'vue';
import { mount, mockScrollTop } from '../../../test';
import { mockScrollTop, mount } from '../../../test';
import Sticky from '..';
Object.defineProperty(window.HTMLElement.prototype, 'clientHeight', {
value: 640,
});
test('should sticky to top after scrolling', async () => {
const wrapper = mount({
render() {
return <Sticky style="height: 10px;">Content</Sticky>;
},
});
expect(wrapper.html()).toMatchSnapshot();
const mockStickyRect = jest
.spyOn(wrapper.element, 'getBoundingClientRect')
.mockReturnValue({
top: -100,
bottom: -90,
});
await mockScrollTop(100);
expect(wrapper.html()).toMatchSnapshot();
mockStickyRect.mockRestore();
});
test('should sticky to bottom after scrolling', async () => {
const wrapper = mount({
render() {
return (
<Sticky style="height: 10px;" offsetBottom={10} position="bottom">
Content
</Sticky>
);
},
});
const mockStickyRect = jest
.spyOn(wrapper.element, 'getBoundingClientRect')
.mockReturnValue({
top: 640,
bottom: 650,
});
await mockScrollTop(0);
expect(wrapper.html()).toMatchSnapshot();
mockStickyRect.mockRestore();
});
test('should update z-index when using z-index prop', async () => {
@@ -27,25 +59,41 @@ test('should update z-index when using z-index prop', async () => {
},
});
const mockStickyRect = jest
.spyOn(wrapper.element, 'getBoundingClientRect')
.mockReturnValue({
top: -100,
bottom: -90,
});
await mockScrollTop(100);
expect(wrapper.html()).toMatchSnapshot();
await mockScrollTop(0);
mockStickyRect.mockRestore();
});
test('should add offset top when using offset-top prop', async () => {
const wrapper = mount({
render() {
return (
<Sticky style="height: 10px;" offsetTop={10}>
<Sticky style="height: 10px;" offsetTop={10} position="top">
Content
</Sticky>
);
},
});
const mockStickyRect = jest
.spyOn(wrapper.element, 'getBoundingClientRect')
.mockReturnValue({
top: -100,
bottom: -90,
});
await mockScrollTop(100);
expect(wrapper.html()).toMatchSnapshot();
await mockScrollTop(0);
mockStickyRect.mockRestore();
});
test('should allow to using offset-top prop with rem unit', async () => {
@@ -63,10 +111,17 @@ test('should allow to using offset-top prop with rem unit', async () => {
},
});
const mockStickyRect = jest
.spyOn(wrapper.element, 'getBoundingClientRect')
.mockReturnValue({
top: -100,
bottom: -90,
});
await mockScrollTop(100);
expect(wrapper.html()).toMatchSnapshot();
await mockScrollTop(0);
mockStickyRect.mockRestore();
window.getComputedStyle = originGetComputedStyle;
});
@@ -83,9 +138,17 @@ test('should allow to using offset-top prop with vw unit', async () => {
},
});
const mockStickyRect = jest
.spyOn(wrapper.element, 'getBoundingClientRect')
.mockReturnValue({
top: -100,
bottom: -90,
});
await mockScrollTop(100);
expect(wrapper.html()).toMatchSnapshot();
await mockScrollTop(0);
mockStickyRect.mockRestore();
});
test('should not trigger scroll event when hidden', () => {
@@ -114,8 +177,8 @@ test('should sticky inside container when using container prop', async () => {
},
render() {
return (
<div ref="container" style="height: 20px;">
<Sticky ref="sticky" style="height: 10px;" container={this.container}>
<div ref="container" style="height: 150px;">
<Sticky ref="sticky" style="height: 44px;" container={this.container}>
Content
</Sticky>
</div>
@@ -123,12 +186,97 @@ test('should sticky inside container when using container prop', async () => {
},
});
await nextTick();
await mockScrollTop(15);
const mockStickyRect = jest
.spyOn(wrapper.element.firstElementChild, 'getBoundingClientRect')
.mockReturnValue({
height: 44,
width: 88,
top: -100,
bottom: -56,
});
const mockContainerRect = jest
.spyOn(wrapper.element, 'getBoundingClientRect')
.mockReturnValue({
top: -100,
bottom: 50,
});
await mockScrollTop(100);
expect(wrapper.html()).toMatchSnapshot();
await mockScrollTop(25);
mockStickyRect.mockReturnValue({
height: 44,
width: 88,
top: -120,
bottom: -76,
});
mockContainerRect.mockReturnValue({
top: -120,
bottom: 30,
});
await mockScrollTop(120);
expect(wrapper.html()).toMatchSnapshot();
await mockScrollTop(0);
mockContainerRect.mockRestore();
mockStickyRect.mockRestore();
});
test('should sticky inside container bottom when using container prop', async () => {
const wrapper = mount({
setup() {
const container = ref();
return {
container,
};
},
render() {
return (
<div ref="container" style="margin-top: 640px">
<div style="height: 150px" />
<Sticky
ref="sticky"
style="height: 44px;"
container={this.container}
position="bottom"
>
Content
</Sticky>
</div>
);
},
});
const mockStickyRect = jest
.spyOn(wrapper.element.children[1], 'getBoundingClientRect')
.mockReturnValue({
height: 44,
width: 88,
top: 690,
bottom: 734,
});
const mockContainerRect = jest
.spyOn(wrapper.element, 'getBoundingClientRect')
.mockReturnValue({
top: 540,
bottom: 734,
});
await mockScrollTop(100);
expect(wrapper.html()).toMatchSnapshot();
mockStickyRect.mockReturnValue({
height: 44,
width: 88,
top: 770,
bottom: 814,
});
mockContainerRect.mockReturnValue({
top: 620,
bottom: 814,
});
await mockScrollTop(20);
expect(wrapper.html()).toMatchSnapshot();
mockContainerRect.mockRestore();
mockStickyRect.mockRestore();
});
test('should emit scroll event when visibility changed', async () => {