mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-26 08:36:19 +08:00
fix: page spinner is styled incorrectly when scrolling (#4163)
* feat: add contributor information to documents * fix: page spinner is styled incorrectly when scrolling
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
* @en_US Layout content height
|
||||
*/
|
||||
export const CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT = `--vben-content-height`;
|
||||
export const CSS_VARIABLE_LAYOUT_CONTENT_WIDTH = `--vben-content-width`;
|
||||
|
||||
/**
|
||||
* @zh_CN 默认命名空间
|
||||
|
@@ -1,140 +1,127 @@
|
||||
import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { getElementVisibleHeight } from './dom'; // 假设函数位于 utils.ts 中
|
||||
import { getElementVisibleRect } from './dom'; // 假设函数位于 utils.ts 中
|
||||
|
||||
describe('getElementVisibleHeight', () => {
|
||||
// Mocking the getBoundingClientRect method
|
||||
const mockGetBoundingClientRect = vi.fn();
|
||||
const originalGetBoundingClientRect = Element.prototype.getBoundingClientRect;
|
||||
|
||||
beforeAll(() => {
|
||||
// Mock getBoundingClientRect method
|
||||
Element.prototype.getBoundingClientRect = mockGetBoundingClientRect;
|
||||
describe('getElementVisibleRect', () => {
|
||||
// 设置浏览器视口尺寸的 mock
|
||||
beforeEach(() => {
|
||||
vi.spyOn(document.documentElement, 'clientHeight', 'get').mockReturnValue(
|
||||
800,
|
||||
);
|
||||
vi.spyOn(window, 'innerHeight', 'get').mockReturnValue(800);
|
||||
vi.spyOn(document.documentElement, 'clientWidth', 'get').mockReturnValue(
|
||||
1000,
|
||||
);
|
||||
vi.spyOn(window, 'innerWidth', 'get').mockReturnValue(1000);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
// Restore original getBoundingClientRect method
|
||||
Element.prototype.getBoundingClientRect = originalGetBoundingClientRect;
|
||||
});
|
||||
|
||||
it('should return 0 if the element is null or undefined', () => {
|
||||
expect(getElementVisibleHeight(null)).toBe(0);
|
||||
expect(getElementVisibleHeight()).toBe(0);
|
||||
});
|
||||
|
||||
it('should return the visible height of the element', () => {
|
||||
// Mock the getBoundingClientRect return value
|
||||
mockGetBoundingClientRect.mockReturnValue({
|
||||
bottom: 500,
|
||||
height: 400,
|
||||
it('should return default rect if element is undefined', () => {
|
||||
expect(getElementVisibleRect()).toEqual({
|
||||
bottom: 0,
|
||||
height: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
toJSON: () => ({}),
|
||||
top: 0,
|
||||
width: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return default rect if element is null', () => {
|
||||
expect(getElementVisibleRect(null)).toEqual({
|
||||
bottom: 0,
|
||||
height: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
width: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return correct visible rect when element is fully visible', () => {
|
||||
const element = {
|
||||
getBoundingClientRect: () => ({
|
||||
bottom: 400,
|
||||
height: 300,
|
||||
left: 200,
|
||||
right: 600,
|
||||
top: 100,
|
||||
width: 400,
|
||||
}),
|
||||
} as HTMLElement;
|
||||
|
||||
expect(getElementVisibleRect(element)).toEqual({
|
||||
bottom: 400,
|
||||
height: 300,
|
||||
left: 200,
|
||||
right: 600,
|
||||
top: 100,
|
||||
width: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 400,
|
||||
});
|
||||
|
||||
const mockElement = document.createElement('div');
|
||||
document.body.append(mockElement);
|
||||
|
||||
// Mocking window.innerHeight and document.documentElement.clientHeight
|
||||
const originalInnerHeight = window.innerHeight;
|
||||
const originalClientHeight = document.documentElement.clientHeight;
|
||||
|
||||
Object.defineProperty(window, 'innerHeight', {
|
||||
value: 600,
|
||||
writable: true,
|
||||
});
|
||||
|
||||
Object.defineProperty(document.documentElement, 'clientHeight', {
|
||||
value: 600,
|
||||
writable: true,
|
||||
});
|
||||
|
||||
expect(getElementVisibleHeight(mockElement)).toBe(400);
|
||||
|
||||
// Restore original values
|
||||
Object.defineProperty(window, 'innerHeight', {
|
||||
value: originalInnerHeight,
|
||||
writable: true,
|
||||
});
|
||||
|
||||
Object.defineProperty(document.documentElement, 'clientHeight', {
|
||||
value: originalClientHeight,
|
||||
writable: true,
|
||||
});
|
||||
|
||||
mockElement.remove();
|
||||
});
|
||||
|
||||
it('should return the visible height when element is partially out of viewport', () => {
|
||||
// Mock the getBoundingClientRect return value
|
||||
mockGetBoundingClientRect.mockReturnValue({
|
||||
bottom: 300,
|
||||
height: 400,
|
||||
left: 0,
|
||||
right: 0,
|
||||
toJSON: () => ({}),
|
||||
top: -100,
|
||||
width: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
it('should return correct visible rect when element is partially off-screen at the top', () => {
|
||||
const element = {
|
||||
getBoundingClientRect: () => ({
|
||||
bottom: 200,
|
||||
height: 250,
|
||||
left: 100,
|
||||
right: 500,
|
||||
top: -50,
|
||||
width: 400,
|
||||
}),
|
||||
} as HTMLElement;
|
||||
|
||||
expect(getElementVisibleRect(element)).toEqual({
|
||||
bottom: 200,
|
||||
height: 200,
|
||||
left: 100,
|
||||
right: 500,
|
||||
top: 0,
|
||||
width: 400,
|
||||
});
|
||||
|
||||
const mockElement = document.createElement('div');
|
||||
document.body.append(mockElement);
|
||||
|
||||
// Mocking window.innerHeight and document.documentElement.clientHeight
|
||||
const originalInnerHeight = window.innerHeight;
|
||||
const originalClientHeight = document.documentElement.clientHeight;
|
||||
|
||||
Object.defineProperty(window, 'innerHeight', {
|
||||
value: 600,
|
||||
writable: true,
|
||||
});
|
||||
|
||||
Object.defineProperty(document.documentElement, 'clientHeight', {
|
||||
value: 600,
|
||||
writable: true,
|
||||
});
|
||||
|
||||
expect(getElementVisibleHeight(mockElement)).toBe(300);
|
||||
|
||||
// Restore original values
|
||||
Object.defineProperty(window, 'innerHeight', {
|
||||
value: originalInnerHeight,
|
||||
writable: true,
|
||||
});
|
||||
|
||||
Object.defineProperty(document.documentElement, 'clientHeight', {
|
||||
value: originalClientHeight,
|
||||
writable: true,
|
||||
});
|
||||
|
||||
mockElement.remove();
|
||||
});
|
||||
|
||||
it('should return 0 if the element is completely out of viewport', () => {
|
||||
// Mock the getBoundingClientRect return value
|
||||
mockGetBoundingClientRect.mockReturnValue({
|
||||
bottom: -100,
|
||||
height: 400,
|
||||
left: 0,
|
||||
right: 0,
|
||||
toJSON: () => ({}),
|
||||
top: -500,
|
||||
width: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
it('should return correct visible rect when element is partially off-screen at the right', () => {
|
||||
const element = {
|
||||
getBoundingClientRect: () => ({
|
||||
bottom: 400,
|
||||
height: 300,
|
||||
left: 800,
|
||||
right: 1200,
|
||||
top: 100,
|
||||
width: 400,
|
||||
}),
|
||||
} as HTMLElement;
|
||||
|
||||
expect(getElementVisibleRect(element)).toEqual({
|
||||
bottom: 400,
|
||||
height: 300,
|
||||
left: 800,
|
||||
right: 1000,
|
||||
top: 100,
|
||||
width: 200,
|
||||
});
|
||||
});
|
||||
|
||||
const mockElement = document.createElement('div');
|
||||
document.body.append(mockElement);
|
||||
it('should return all zeros when element is completely off-screen', () => {
|
||||
const element = {
|
||||
getBoundingClientRect: () => ({
|
||||
bottom: 1200,
|
||||
height: 300,
|
||||
left: 1100,
|
||||
right: 1400,
|
||||
top: 900,
|
||||
width: 300,
|
||||
}),
|
||||
} as HTMLElement;
|
||||
|
||||
expect(getElementVisibleHeight(mockElement)).toBe(0);
|
||||
|
||||
mockElement.remove();
|
||||
expect(getElementVisibleRect(element)).toEqual({
|
||||
bottom: 800,
|
||||
height: 0,
|
||||
left: 1100,
|
||||
right: 1000,
|
||||
top: 900,
|
||||
width: 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -1,12 +1,28 @@
|
||||
export interface VisibleDomRect {
|
||||
bottom: number;
|
||||
height: number;
|
||||
left: number;
|
||||
right: number;
|
||||
top: number;
|
||||
width: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取元素可见高度
|
||||
* 获取元素可见信息
|
||||
* @param element
|
||||
*/
|
||||
function getElementVisibleHeight(
|
||||
export function getElementVisibleRect(
|
||||
element?: HTMLElement | null | undefined,
|
||||
): number {
|
||||
): VisibleDomRect {
|
||||
if (!element) {
|
||||
return 0;
|
||||
return {
|
||||
bottom: 0,
|
||||
height: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
width: 0,
|
||||
};
|
||||
}
|
||||
const rect = element.getBoundingClientRect();
|
||||
const viewHeight = Math.max(
|
||||
@@ -17,7 +33,20 @@ function getElementVisibleHeight(
|
||||
const top = Math.max(rect.top, 0);
|
||||
const bottom = Math.min(rect.bottom, viewHeight);
|
||||
|
||||
return Math.max(0, bottom - top);
|
||||
}
|
||||
const viewWidth = Math.max(
|
||||
document.documentElement.clientWidth,
|
||||
window.innerWidth,
|
||||
);
|
||||
|
||||
export { getElementVisibleHeight };
|
||||
const left = Math.max(rect.left, 0);
|
||||
const right = Math.min(rect.right, viewWidth);
|
||||
|
||||
return {
|
||||
bottom,
|
||||
height: Math.max(0, bottom - top),
|
||||
left,
|
||||
right,
|
||||
top,
|
||||
width: Math.max(0, right - left),
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user