Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ function Example(): JSX.Element {
const vComponents = useMemo(() => {
// 使用VList 即可有虚拟列表的效果
return VList({
height: 1000 // 此值和scrollY值相同. 必传. (required). same value for scrolly
height: 1000 // 此值和scrollY值相同 (不传或者传string类型会自动计算表格高度) same value for scrolly
})
}, [])

Expand All @@ -102,7 +102,7 @@ ReactDom.render(<Example />, dom)

```tsx
VList({
height: number | string, // (必填) 对应scrollY.
height: number | string, // (可选) 对应scrollY. (not required, if not set, will auto calculate table height)
onReachEnd: () => void, // (可选) 滚动条滚到底部触发api. (scrollbar to the end)
onScroll: () => void, // (可选) 滚动时触发的api. (triggered by scrolling)
vid: string, // (可选, 如果同一页面存在多个虚拟表格时必填.) 唯一标识. (unique vid, required when exist more vitual table on a page)
Expand Down
3 changes: 3 additions & 0 deletions docs/demo/AutoHeightTable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## AutoHeightTable

<code src="../examples/AutoHeightTable.tsx">
69 changes: 69 additions & 0 deletions docs/examples/AutoHeightTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React, { useState, useEffect, useMemo } from 'react';
import { Table } from 'antd';
import { VList } from '../../src/index';
import 'antd/dist/antd.css';

type DataSourceType = { [key: string]: string }
function AutoHeightTable() {
const [dataSource, setDataSource] = useState<DataSourceType[]>([]);

useEffect(() => {
const tempDataSource: DataSourceType[] = [];
for (let i = 0; i < 1000; i += 1) {
tempDataSource.push({
company_name: `aaa${i} 富士山下的你好美 你知道吗 aaa${i} 富士山下的你好美 你知道吗 aaa${i} 富士山下的你好美 你知道吗`,
company_name1: `aaa${i} index index index index`,
company_name2: `aaa${i} company index index index`,

company_name3: `aaa${i} company company index index`,
company_name4: `aaa${i} company company company index`,
company_name5: `aaa${i} company company company company`,
company_name6: `aaa${i} company index index company`,
});
}

setDataSource(tempDataSource);
}, []);

const columns: any[] = [
{
title: '序号',
key: 'id',
fixed: 'left',
render(text, record, index) {
return index + 1;
},
width: 100,
},
{
title: '公司',
dataIndex: 'company_name',
width: 200,
},
{
title: '公司1',
dataIndex: 'company_name1',
width: 200,
},
{
title: '公司2',
dataIndex: 'company_name2',
width: 200,
},
];

const vc1 = useMemo(() => VList({ }), []);


return <Table
columns={columns}
dataSource={dataSource}
pagination={false}
scroll={{ y: 'calc(100vh - 55px)', x: '100%' }}
rowKey="company_name"
components={vc1}
/>
;
}

export default AutoHeightTable;
91 changes: 79 additions & 12 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import React, {
useState,
useMemo,
} from 'react'
import { throttle, debounce } from 'lodash-es'
import { throttle, debounce, isNumber } from 'lodash-es'

import './style.css'

Expand All @@ -27,6 +27,52 @@ const initialState = {
totalLen: 0,
}

/**
* @description: 10 -> 10,
* @description: 10px -> 10,
* @description: 90% -> height * 0.9
* @description: calc(100% - 32px) -> height * 1 - 32
* @description: calc(100vh - 32px) -> documentHeight * 1 - 32
* @param {*} ele
* @param {string & number} maxWidth
* @return {*}
*/
const transitionHeight = (parentHeight: number, height: string | number) => {
const documentHeight = document.documentElement.offsetHeight;
if (!height) return parentHeight;

if (typeof height === 'number') {
return height; // 如果父元素的宽度小于传入的最大宽度,返回父元素的宽度
}

const numMatch = height.match(/^(\d+)(px)?$/);
if (numMatch) {
return +numMatch[1]; // 如果父元素的宽度小于传入的最大宽度,返回父元素的宽度
}

const percentMatch = height.match(/^(\d+)%$/);
if (percentMatch) {
return parentHeight * (parseInt(percentMatch[1]) / 100);
}

const vhMatch = height.match(/^(\d+)(vh)?$/);
if (vhMatch) {
return documentHeight * (parseInt(vhMatch[1]) / 100);
}

const relativeMatch = height.match(/^calc\((\d+)% - (\d+)px\)$/);
if (relativeMatch) {
return parentHeight * (parseInt(relativeMatch[1]) / 100) - parseInt(relativeMatch[2]);
}

const absoluteMatch = height.match(/^calc\((\d+)vh - (\d+)px\)$/);
if (absoluteMatch) {
return documentHeight * (parseInt(absoluteMatch[1]) / 100) - parseInt(absoluteMatch[2]);
}

return parentHeight;
};

function reducer(state, action) {
const { curScrollTop, rowHeight, totalLen, ifScrollTopClear } = action

Expand Down Expand Up @@ -219,20 +265,41 @@ function VTable(props: any, otherParams): JSX.Element {
return temp
}, [state.rowHeight, totalLen])

const [parentHeight, setParentHeight] = useState<number>()
useEffect(() => {
const parentElement = wrap_tableRef.current?.parentElement
const updateContainerHeight = () => {
if (!parentElement) return;
const containerHeight = parentElement.getBoundingClientRect()?.height;

setParentHeight(containerHeight);
};

setTimeout(() => {
updateContainerHeight()
})
// 在height为固定高度的时候不进行监听
if (isNumber(scrollY) || /^\b\d+px\b$/.test(scrollY)) return;

const ResizeObserverImpl =
typeof window !== 'undefined' && 'ResizeObserver' in window
? window['ResizeObserver']
: null;
if (!ResizeObserverImpl) {
console.warn('ResizeObserver is not supported in this environment.');
return;
}
const resizeObserver = new ResizeObserverImpl(updateContainerHeight);
resizeObserver.observe(parentElement);
return () => resizeObserver.disconnect();
}, [])

// table的scrollY值
const [tableScrollY, setTableScrollY] = useState(0)

// tableScrollY 随scrollY / tableHeight 进行变更
useEffect(() => {
let temp = 0

if (typeof scrollY === 'string') {
temp =
(wrap_tableRef.current?.parentNode as HTMLElement)
?.offsetHeight ?? 0
} else {
temp = scrollY
}
let temp = transitionHeight(parentHeight ?? 0, scrollY) ?? 0

// if (isNumber(tableHeight) && tableHeight < temp) {
// temp = tableHeight;
Expand All @@ -244,7 +311,7 @@ function VTable(props: any, otherParams): JSX.Element {
}

setTableScrollY(temp)
}, [scrollY, tableHeight])
}, [scrollY, tableHeight, parentHeight])

// 渲染的条数
const renderLen = useMemo<number>(() => {
Expand Down Expand Up @@ -397,7 +464,7 @@ function VTable(props: any, otherParams): JSX.Element {

// ================导出===================
export function VList(props: {
height: number | string
height?: number | string
// 到底的回调函数
onReachEnd?: () => void
onScroll?: () => void
Expand Down