diff --git a/README.md b/README.md
index 5a2e74a..5991d42 100644
--- a/README.md
+++ b/README.md
@@ -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
})
}, [])
@@ -102,7 +102,7 @@ ReactDom.render(, 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)
diff --git a/docs/demo/AutoHeightTable.md b/docs/demo/AutoHeightTable.md
new file mode 100644
index 0000000..38f6a2a
--- /dev/null
+++ b/docs/demo/AutoHeightTable.md
@@ -0,0 +1,3 @@
+## AutoHeightTable
+
+
\ No newline at end of file
diff --git a/docs/examples/AutoHeightTable.tsx b/docs/examples/AutoHeightTable.tsx
new file mode 100644
index 0000000..7909769
--- /dev/null
+++ b/docs/examples/AutoHeightTable.tsx
@@ -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([]);
+
+ 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
+ ;
+}
+
+export default AutoHeightTable;
diff --git a/src/index.tsx b/src/index.tsx
index eecb525..b9e35d0 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -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'
@@ -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
@@ -219,20 +265,41 @@ function VTable(props: any, otherParams): JSX.Element {
return temp
}, [state.rowHeight, totalLen])
+ const [parentHeight, setParentHeight] = useState()
+ 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;
@@ -244,7 +311,7 @@ function VTable(props: any, otherParams): JSX.Element {
}
setTableScrollY(temp)
- }, [scrollY, tableHeight])
+ }, [scrollY, tableHeight, parentHeight])
// 渲染的条数
const renderLen = useMemo(() => {
@@ -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