Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

antd-table-infinity

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

antd-table-infinity - npm Package Compare versions

Comparing version 1.1.3 to 1.1.5

3

es/PageTable/index.js

@@ -440,3 +440,4 @@ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

shouldUpdate = [1, maxPage, maxPage - 1, maxPage - 2].includes(currentPage) ? dataSource.length > 0 : [// 如果已经加载3页数据,需要更新视图,否则不在 fullLoading 状态,即使数据不满3页也需要更新视图
...(this.fullLoading ? [] : [0, pageSize, pageSize * 2]), pageSize * 3].includes(dataSource.length);
// 兼容部份项目,每页,可能多一个条目的情况,如一系列数据,有个合计行
...(this.fullLoading ? [] : [0, pageSize, pageSize + 1, pageSize * 2, pageSize * 2 + 1, pageSize * 2 + 2]), pageSize * 3, pageSize * 3 + 1, pageSize * 3 + 2, pageSize * 3 + 3].includes(dataSource.length);
debug && console.log('shouldUpdate:3Page', {

@@ -443,0 +444,0 @@ currentPage,

@@ -455,3 +455,4 @@ "use strict";

shouldUpdate = [1, maxPage, maxPage - 1, maxPage - 2].includes(currentPage) ? dataSource.length > 0 : [// 如果已经加载3页数据,需要更新视图,否则不在 fullLoading 状态,即使数据不满3页也需要更新视图
...(this.fullLoading ? [] : [0, pageSize, pageSize * 2]), pageSize * 3].includes(dataSource.length);
// 兼容部份项目,每页,可能多一个条目的情况,如一系列数据,有个合计行
...(this.fullLoading ? [] : [0, pageSize, pageSize + 1, pageSize * 2, pageSize * 2 + 1, pageSize * 2 + 2]), pageSize * 3, pageSize * 3 + 1, pageSize * 3 + 2, pageSize * 3 + 3].includes(dataSource.length);
debug && console.log('shouldUpdate:3Page', {

@@ -458,0 +459,0 @@ currentPage,

{
"name": "antd-table-infinity",
"version": "1.1.3",
"version": "1.1.5",
"scripts": {

@@ -80,3 +80,2 @@ "storybook": "start-storybook -p 9001 -c .storybook",

"dependencies": {
"antd-table-infinity": "^1.1.2",
"intersection-observer": "^0.5.1",

@@ -83,0 +82,0 @@ "lodash.throttle": "^4.1.1"

@@ -10,98 +10,98 @@ import React, { Component, Fragment } from 'react'

const fetchDebounce = (() => {
const loading = []
return ({ page, pageSize, onFetch }) => {
const now = Date.now()
if (!loading[page] || (loading[page] && now - loading[page] > 1000)) {
onFetch({ page, pageSize })
}
loading[page] = now
}
const loading = []
return ({ page, pageSize, onFetch }) => {
const now = Date.now()
if (!loading[page] || (loading[page] && now - loading[page] > 1000)) {
onFetch({ page, pageSize })
}
loading[page] = now
}
})()
function getCachePage({ step, maxPage, pageSize, onFetch, loading, cacheData, currentPage }) {
const pageBefore = currentPage - step
const pageAfter = currentPage + step
const cachePageDataBefore = cacheData[pageBefore]
const cachePageData = cacheData[currentPage]
const cachePageDataAfter = cacheData[pageAfter]
if (!loading) {
!cachePageData &&
currentPage > 0 &&
currentPage <= maxPage &&
fetchDebounce({ page: currentPage, pageSize, onFetch })
!cachePageDataBefore &&
pageBefore > 0 &&
pageBefore <= maxPage &&
fetchDebounce({ page: pageBefore, pageSize, onFetch })
!cachePageDataAfter &&
pageAfter > 0 &&
pageAfter <= maxPage &&
fetchDebounce({ page: pageAfter, pageSize, onFetch })
const pageBefore = currentPage - step
const pageAfter = currentPage + step
const cachePageDataBefore = cacheData[pageBefore]
const cachePageData = cacheData[currentPage]
const cachePageDataAfter = cacheData[pageAfter]
if (!loading) {
!cachePageData &&
currentPage > 0 &&
currentPage <= maxPage &&
fetchDebounce({ page: currentPage, pageSize, onFetch })
!cachePageDataBefore &&
pageBefore > 0 &&
pageBefore <= maxPage &&
fetchDebounce({ page: pageBefore, pageSize, onFetch })
!cachePageDataAfter &&
pageAfter > 0 &&
pageAfter <= maxPage &&
fetchDebounce({ page: pageAfter, pageSize, onFetch })
}
let lastOwnDataPage = currentPage
if (cachePageDataAfter) {
lastOwnDataPage = pageAfter
} else if (cachePageData) {
lastOwnDataPage = currentPage
} else if (cachePageDataBefore) {
lastOwnDataPage = pageBefore
}
let lastOwnDataPage = currentPage
if (cachePageDataAfter) {
lastOwnDataPage = pageAfter
} else if (cachePageData) {
lastOwnDataPage = currentPage
} else if (cachePageDataBefore) {
lastOwnDataPage = pageBefore
}
return [cachePageDataBefore || [], cachePageData || [], cachePageDataAfter || [], lastOwnDataPage]
return [cachePageDataBefore || [], cachePageData || [], cachePageDataAfter || [], lastOwnDataPage]
}
const computeState = (
{ pageSize, onFetch, loading, total, bidirectionalCachePages: cachePages, dataSource: [page, data] },
{ maxPage, currentPage, cacheData, rowHeight },
{ pageSize, onFetch, loading, total, bidirectionalCachePages: cachePages, dataSource: [page, data] },
{ maxPage, currentPage, cacheData, rowHeight },
) => {
let bidirectionalCachePages = cachePages
let newCacheData = cacheData
let bidirectionalCachePages = cachePages
let newCacheData = cacheData
if (cachePages < 1) {
bidirectionalCachePages = 1
}
if (bidirectionalCachePages * 2 + 1 < maxPage) {
let startPage = currentPage - bidirectionalCachePages
startPage = startPage < 1 ? 1 : startPage
if (cachePages < 1) {
bidirectionalCachePages = 1
}
if (bidirectionalCachePages * 2 + 1 < maxPage) {
let startPage = currentPage - bidirectionalCachePages
startPage = startPage < 1 ? 1 : startPage
let endPage = currentPage + bidirectionalCachePages
endPage = endPage > maxPage ? maxPage : endPage
let endPage = currentPage + bidirectionalCachePages
endPage = endPage > maxPage ? maxPage : endPage
cacheData[page] = data // eslint-disable-line
newCacheData = Array.from({ length: maxPage })
cacheData[page] = data // eslint-disable-line
newCacheData = Array.from({ length: maxPage })
Array.prototype.splice.apply(
newCacheData,
[startPage, endPage - startPage + 1].concat(cacheData.slice(startPage, endPage + 1)),
)
}
newCacheData[page] = data
Array.prototype.splice.apply(
newCacheData,
[startPage, endPage - startPage + 1].concat(cacheData.slice(startPage, endPage + 1)),
)
}
newCacheData[page] = data
const [cachePageDataBefore, cachePageData, cachePageDataAfter, lastOwnDataPage] = getCachePage({
step: 1,
maxPage,
pageSize,
onFetch,
loading,
cacheData: newCacheData,
currentPage,
})
const [cachePageDataBefore, cachePageData, cachePageDataAfter, lastOwnDataPage] = getCachePage({
step: 1,
maxPage,
pageSize,
onFetch,
loading,
cacheData: newCacheData,
currentPage,
})
const upperHeight = Math.round((currentPage - 1 - (cachePageDataBefore.length ? 1 : 0)) * pageSize * rowHeight)
const upperHeight = Math.round((currentPage - 1 - (cachePageDataBefore.length ? 1 : 0)) * pageSize * rowHeight)
const underHeight = Math.round(
// 已经是最后一页,直接返回0,否则如果有零头total % pageSize,需要加上不满一个page的零头lastOwnDataPageLength,但需要少加一个整页pageSize
maxPage === lastOwnDataPage ? 0 : ((maxPage - lastOwnDataPage) * pageSize + (total % pageSize)) * rowHeight,
)
const dataSource = cachePageDataBefore.concat(cachePageData).concat(cachePageDataAfter)
const underHeight = Math.round(
// 已经是最后一页,直接返回0,否则如果有零头total % pageSize,需要加上不满一个page的零头lastOwnDataPageLength,但需要少加一个整页pageSize
maxPage === lastOwnDataPage ? 0 : ((maxPage - lastOwnDataPage) * pageSize + (total % pageSize)) * rowHeight,
)
const dataSource = cachePageDataBefore.concat(cachePageData).concat(cachePageDataAfter)
return {
hasCacheBefore: !!cachePageDataBefore.length,
hasCache: !!cachePageData.length,
hasCacheAfter: !!cachePageDataAfter.length,
cacheData: newCacheData,
dataSource,
underHeight,
upperHeight,
}
return {
hasCacheBefore: !!cachePageDataBefore.length,
hasCache: !!cachePageData.length,
hasCacheAfter: !!cachePageDataAfter.length,
cacheData: newCacheData,
dataSource,
underHeight,
upperHeight,
}
}

@@ -111,482 +111,466 @@

class InfinityTable extends Component {
static PlaceHolder({ height, domNode, loading, loadingIndicator }) {
return (
domNode &&
ReactDOM.createPortal(<div style={{ height: `${height}px` }}>{loading && loadingIndicator} </div>, domNode)
)
}
static LoadingPlaceHolder({ domNode, loading, loadingIndicator }) {
return domNode && ReactDOM.createPortal(loading ? loadingIndicator : <div />, domNode)
}
state = {
scrollTop: 0, // 滚动条位置
dataSource: [], // DOM上显示的数据
rowHeight: 0, // 每行的实际高度
cacheData: [], // 缓存的数据集大小
currentPage: 1, // 当前页位置
underHeight: 0, // 下撑高
upperHeight: 0, // 上撑高
}
static getDerivedStateFromProps(props, prevState) {
return computeState(props, prevState)
}
static PlaceHolder({ height, domNode, loading, loadingIndicator }) {
return (
domNode &&
ReactDOM.createPortal(<div style={{ height: `${height}px` }}>{loading && loadingIndicator} </div>, domNode)
)
}
static LoadingPlaceHolder({ domNode, loading, loadingIndicator }) {
return domNode && ReactDOM.createPortal(loading ? loadingIndicator : <div />, domNode)
}
state = {
scrollTop: 0, // 滚动条位置
dataSource: [], // DOM上显示的数据
rowHeight: 0, // 每行的实际高度
cacheData: [], // 缓存的数据集大小
currentPage: 1, // 当前页位置
underHeight: 0, // 下撑高
upperHeight: 0, // 上撑高
}
static getDerivedStateFromProps(props, prevState) {
return computeState(props, prevState)
}
componentDidMount() {
/* eslint-disable */
this.refRoot = ReactDOM.findDOMNode(this)
this.refScroll = this.refRoot.getElementsByClassName('ant-table-body')[0]
this.refTable = this.refScroll.getElementsByTagName('tbody')[0]
/* eslint-enabled */
this.createUnderPlaceholder()
this.createUpperPlaceholder()
this.setStateWithThrottle = throttle(this.updateTable, 0)
this.props.onScroll && this.refScroll.addEventListener('scroll', this.props.onScroll)
componentDidMount() {
/* eslint-disable */
this.refRoot = ReactDOM.findDOMNode(this)
this.refScroll = this.refRoot.getElementsByClassName('ant-table-body')[0]
this.refTable = this.refScroll.getElementsByTagName('tbody')[0]
/* eslint-enabled */
this.createUnderPlaceholder()
this.createUpperPlaceholder()
this.setStateWithThrottle = throttle(this.updateTable, 0)
this.props.onScroll && this.refScroll.addEventListener('scroll', this.props.onScroll)
if (this.refScroll) {
this.io = new IntersectionObserver(
changes => {
const { debug } = this.props
let shouldUpdate = true
this.ioTargetState = changes.reduce((result, change) => {
const ret = { ...result }
switch (change.target) {
case this.refPageBoundaryBefore:
ret.refPageBoundaryBefore = change
// Bug fix:
// 向下滚动的时候,如果边界第一行数据触发,不需要更新视图,因为上一页的最后一行已经触发了视图更新,
// 但是用户通过点击分页切换,而不是滚动的情况例外,因为此时需要更新页码
if (
!this.isPaginationClick &&
changes.length === 1 &&
this.state.direction === 'down'
) {
shouldUpdate = false
}
if (this.refScroll) {
this.io = new IntersectionObserver(
changes => {
const { debug } = this.props
let shouldUpdate = true
this.ioTargetState = changes.reduce((result, change) => {
const ret = { ...result }
switch (change.target) {
case this.refPageBoundaryBefore:
ret.refPageBoundaryBefore = change
// Bug fix:
// 向下滚动的时候,如果边界第一行数据触发,不需要更新视图,因为上一页的最后一行已经触发了视图更新,
// 但是用户通过点击分页切换,而不是滚动的情况例外,因为此时需要更新页码
if (!this.isPaginationClick && changes.length === 1 && this.state.direction === 'down') {
shouldUpdate = false
}
break
case this.refPageBoundaryAfter:
ret.refPageBoundaryAfter = change
// Bug fix:
// 向上滚动的时候,如果边界最后行数据触发,不需要更新视图,因为上一页的第一行已经触发了视图更新
// 但是用户通过点击分页切换,而不是滚动的情况例外,因为此时需要更新页码
if (!this.isPaginationClick && changes.length === 1 && this.state.direction === 'up') {
shouldUpdate = false
}
break
default: // console.log(change)
}
return ret
}, this.ioTargetState)
break
case this.refPageBoundaryAfter:
ret.refPageBoundaryAfter = change
// Bug fix:
// 向上滚动的时候,如果边界最后行数据触发,不需要更新视图,因为上一页的第一行已经触发了视图更新
// 但是用户通过点击分页切换,而不是滚动的情况例外,因为此时需要更新页码
if (!this.isPaginationClick && changes.length === 1 && this.state.direction === 'up') {
shouldUpdate = false
}
break
default: // console.log(change)
}
return ret
}, this.ioTargetState)
this.isPaginationClick = false
this.isPaginationClick = false
debug &&
console.log('shouldUpdate:IntersectionObserver', {
shouldUpdate,
changes,
})
debug &&
console.log('shouldUpdate:IntersectionObserver', {
shouldUpdate,
changes,
})
shouldUpdate && this.setStateWithThrottle()
},
{
root: this.refScroll,
threshold: [0, 1],
},
)
this.toggleObserver()
}
shouldUpdate && this.setStateWithThrottle()
},
{
root: this.refScroll,
threshold: [0, 1],
},
)
this.toggleObserver()
}
this.props.onFetch({ page: 1, pageSize: this.props.pageSize })
this.props.onFetch({ page: 1, pageSize: this.props.pageSize })
new Promise(reslove => {
this.initialReslove = reslove
}).then(() => {
const {
pageSize,
pagination: { defaultCurrent = 1 },
} = this.props
this.createLoadingPlaceholder() // fullLoading
this.scrollToPage(defaultCurrent)
const visibleRowCount = Math.round(this.refScroll.clientHeight / this.state.rowHeight)
this.isReady = true
if (pageSize < visibleRowCount) {
console.warn(
`pagesize(${pageSize}) less than visible row count(${visibleRowCount}), maybe you set error!`,
)
}
})
}
shouldComponentUpdate(nextProps, nextState) {
const { pageSize, debug } = nextProps
const { maxPage, currentPage, dataSource, direction, rowHeight } = nextState
let shouldUpdate = true
new Promise(reslove => {
this.initialReslove = reslove
}).then(() => {
const {
pageSize,
pagination: { defaultCurrent = 1 },
} = this.props
this.createLoadingPlaceholder() // fullLoading
this.scrollToPage(defaultCurrent)
const visibleRowCount = Math.round(this.refScroll.clientHeight / this.state.rowHeight)
this.isReady = true
if (pageSize < visibleRowCount) {
console.warn(`pagesize(${pageSize}) less than visible row count(${visibleRowCount}), maybe you set error!`)
}
})
}
shouldComponentUpdate(nextProps, nextState) {
const { pageSize, debug } = nextProps
const { maxPage, currentPage, dataSource, direction, rowHeight } = nextState
let shouldUpdate = true
// 有且仅有当前页上下边界同时触发时,表示更换边界,不需要更新
if (this.isPageBoundary) {
shouldUpdate = false
this.isPageBoundary = false
}
debug && console.log('shouldUpdate:updateBoundary', { shouldUpdate })
// 有且仅有当前页上下边界同时触发时,表示更换边界,不需要更新
if (this.isPageBoundary) {
shouldUpdate = false
this.isPageBoundary = false
}
debug && console.log('shouldUpdate:updateBoundary', { shouldUpdate })
if (shouldUpdate && !this.isInitial) {
let currentPageReal = currentPage
if (shouldUpdate && !this.isInitial) {
let currentPageReal = currentPage
// 由于state中的currentPage延迟与真实的currentPage不一致,当出现这种情况时,强制updateTable()
currentPageReal = Math.floor(this.refScroll.scrollTop / (pageSize * rowHeight)) + 1 || 1
currentPageReal = currentPageReal > maxPage ? maxPage : currentPageReal
if (currentPageReal !== currentPage) {
this.updateTable()
shouldUpdate = false
}
// 由于state中的currentPage延迟与真实的currentPage不一致,当出现这种情况时,强制updateTable()
currentPageReal = Math.floor(this.refScroll.scrollTop / (pageSize * rowHeight)) + 1 || 1
currentPageReal = currentPageReal > maxPage ? maxPage : currentPageReal
if (currentPageReal !== currentPage) {
this.updateTable()
shouldUpdate = false
}
debug &&
console.log('shouldUpdate:currentPageReal', {
currentPageReal,
currentPage,
shouldUpdate,
})
}
debug &&
console.log('shouldUpdate:currentPageReal', {
currentPageReal,
currentPage,
shouldUpdate,
})
}
if (shouldUpdate) {
const { refPageBoundaryBefore, refPageBoundaryAfter } = this.ioTargetState
if (shouldUpdate) {
const { refPageBoundaryBefore, refPageBoundaryAfter } = this.ioTargetState
switch (direction) {
case 'up':
if (
this.state.hasCacheAfter &&
currentPage < maxPage - 2 && // Bug fix: 如果是最后三页向后点击切换,需要刷新视图,否则页码表记停留在前一页
refPageBoundaryBefore &&
refPageBoundaryBefore.intersectionRatio > 0
)
shouldUpdate = false
break
switch (direction) {
case 'up':
if (
this.state.hasCacheAfter &&
currentPage < maxPage - 2 && // Bug fix: 如果是最后三页向后点击切换,需要刷新视图,否则页码表记停留在前一页
refPageBoundaryBefore &&
refPageBoundaryBefore.intersectionRatio > 0
)
shouldUpdate = false
break
case 'down':
if (
this.state.currentPage === currentPage &&
this.state.hasCacheAfter && // Bug fix: 可能存在3页数据已经加载到了, 但之前没有刷新的情况,所以需要刷新,判断特征是之前的数据小于3页
refPageBoundaryAfter &&
refPageBoundaryAfter.intersectionRatio > 0
)
shouldUpdate = false
}
case 'down':
if (
this.state.currentPage === currentPage &&
this.state.hasCacheAfter && // Bug fix: 可能存在3页数据已经加载到了, 但之前没有刷新的情况,所以需要刷新,判断特征是之前的数据小于3页
refPageBoundaryAfter &&
refPageBoundaryAfter.intersectionRatio > 0
)
shouldUpdate = false
}
debug &&
console.log('shouldUpdate:verboseBoundary', {
shouldUpdate,
direction,
dataSource,
Before: refPageBoundaryBefore && refPageBoundaryBefore.intersectionRatio,
After: refPageBoundaryAfter && refPageBoundaryAfter.intersectionRatio,
})
}
debug &&
console.log('shouldUpdate:verboseBoundary', {
shouldUpdate,
direction,
dataSource,
Before: refPageBoundaryBefore && refPageBoundaryBefore.intersectionRatio,
After: refPageBoundaryAfter && refPageBoundaryAfter.intersectionRatio,
})
}
if (shouldUpdate) {
shouldUpdate = [1, maxPage, maxPage - 1, maxPage - 2].includes(currentPage)
? dataSource.length > 0
: [
// 如果已经加载3页数据,需要更新视图,否则不在 fullLoading 状态,即使数据不满3页也需要更新视图
...(this.fullLoading ? [] : [0, pageSize, pageSize * 2]),
pageSize * 3,
].includes(dataSource.length)
if (shouldUpdate) {
shouldUpdate = [1, maxPage, maxPage - 1, maxPage - 2].includes(currentPage)
? dataSource.length > 0
: [
// 如果已经加载3页数据,需要更新视图,否则不在 fullLoading 状态,即使数据不满3页也需要更新视图
// 兼容部份项目,每页,可能多一个条目的情况,如一系列数据,有个合计行
...(this.fullLoading ? [] : [0, pageSize, pageSize + 1, pageSize * 2, pageSize * 2 + 1, pageSize * 2 + 2]),
pageSize * 3,
pageSize * 3 + 1,
pageSize * 3 + 2,
pageSize * 3 + 3,
].includes(dataSource.length)
debug &&
console.log('shouldUpdate:3Page', {
currentPage,
dataSource,
shouldUpdate,
state: this.state,
nextState,
})
}
debug &&
console.log('shouldUpdate:3Page', {
currentPage,
dataSource,
shouldUpdate,
state: this.state,
nextState,
})
}
return shouldUpdate
}
componentDidUpdate(preProps, preState) {
const { hasCache, hasCacheBefore, currentPage, dataSource, maxPage } = this.state
const { pageSize, debug } = this.props
return shouldUpdate
}
componentDidUpdate(preProps, preState) {
const { hasCache, hasCacheBefore, currentPage, dataSource, maxPage } = this.state
const { pageSize, debug } = this.props
if (!this.isInitial) {
let before, after
if (!this.isInitial) {
let before, after
if (hasCache && hasCacheBefore) {
if (currentPage === 1 || currentPage === maxPage - 1) {
before = 0
after = pageSize - 1
} else if (currentPage === maxPage) {
before = 0
after = dataSource.length - 1
} else {
before = pageSize
after = pageSize * 2 - 1
}
if (hasCache && hasCacheBefore) {
if (currentPage === 1 || currentPage === maxPage - 1) {
before = 0
after = pageSize - 1
} else if (currentPage === maxPage) {
before = 0
after = dataSource.length - 1
} else {
before = pageSize
after = pageSize * 2 - 1
}
if (this.refPageBoundaryBefore !== this.refTable.children[before]) {
this.refPageBoundaryBefore && this.io.unobserve(this.refPageBoundaryBefore)
this.refPageBoundaryAfter && this.io.unobserve(this.refPageBoundaryAfter)
if (this.refPageBoundaryBefore !== this.refTable.children[before]) {
this.refPageBoundaryBefore && this.io.unobserve(this.refPageBoundaryBefore)
this.refPageBoundaryAfter && this.io.unobserve(this.refPageBoundaryAfter)
this.refPageBoundaryBefore = this.refTable.children[before]
this.refPageBoundaryAfter = this.refTable.children[after]
this.refPageBoundaryBefore = this.refTable.children[before]
this.refPageBoundaryAfter = this.refTable.children[after]
this.refPageBoundaryAfter && this.io.observe(this.refPageBoundaryAfter)
this.refPageBoundaryBefore && this.io.observe(this.refPageBoundaryBefore)
this.refPageBoundaryAfter && this.io.observe(this.refPageBoundaryAfter)
this.refPageBoundaryBefore && this.io.observe(this.refPageBoundaryBefore)
debug &&
this.refPageBoundaryBefore &&
console.log('componentDidUpdate', this.refPageBoundaryBefore.innerText)
debug &&
this.refPageBoundaryAfter &&
console.log('componentDidUpdate', this.refPageBoundaryAfter.innerText)
debug && this.refPageBoundaryBefore && console.log('componentDidUpdate', this.refPageBoundaryBefore.innerText)
debug && this.refPageBoundaryAfter && console.log('componentDidUpdate', this.refPageBoundaryAfter.innerText)
this.isPageBoundary = true
}
}
const emptyPlaceholder = this.refRoot.querySelector('.ant-table-placeholder')
emptyPlaceholder && (emptyPlaceholder.style.display = 'none')
}
}
componentWillUnmount() {
this.props.onScroll && this.refScroll.removeEventListener('scroll', this.props.onScroll)
this.io.disconnect()
}
isInitial = true // 初始状态,未渲染任何数据
isReady = false // 已渲染首屏数据,可交互的状态
isPageBoundary = false // 当前页,上下边界更新
isPaginationClick = false
refUpperPlaceholder = null
refUnderPlaceholder = null
refLoadingPlaceholder = null
refScroll = null
refTable = null
refFooter = null
refPageBoundaryBefore = null // 当前页的第一条DOM数据
refPageBoundaryAfter = null // 当前页的最后一条DOM数据
ioTargetState = {
refUnderPlaceholder: null,
refUpperPlaceholder: null,
refTable: null,
refPageBoundaryBefore: null,
refPageBoundaryAfter: null,
}
createLoadingPlaceholder() {
const refLoadingPlaceholder = document.createElement('div')
refLoadingPlaceholder.setAttribute('id', 'refLoadingPlaceholder')
const clientRect = this.refScroll.getBoundingClientRect()
refLoadingPlaceholder.setAttribute(
'style',
`position:fixed; width:${clientRect.width}px; height:${clientRect.height}px`,
)
this.isPageBoundary = true
}
}
const emptyPlaceholder = this.refRoot.querySelector('.ant-table-placeholder')
emptyPlaceholder && (emptyPlaceholder.style.display = 'none')
}
}
componentWillUnmount() {
this.props.onScroll && this.refScroll.removeEventListener('scroll', this.props.onScroll)
this.io.disconnect()
}
isInitial = true // 初始状态,未渲染任何数据
isReady = false // 已渲染首屏数据,可交互的状态
isPageBoundary = false // 当前页,上下边界更新
isPaginationClick = false
refUpperPlaceholder = null
refUnderPlaceholder = null
refLoadingPlaceholder = null
refScroll = null
refTable = null
refFooter = null
refPageBoundaryBefore = null // 当前页的第一条DOM数据
refPageBoundaryAfter = null // 当前页的最后一条DOM数据
ioTargetState = {
refUnderPlaceholder: null,
refUpperPlaceholder: null,
refTable: null,
refPageBoundaryBefore: null,
refPageBoundaryAfter: null,
}
createLoadingPlaceholder() {
const refLoadingPlaceholder = document.createElement('div')
refLoadingPlaceholder.setAttribute('id', 'refLoadingPlaceholder')
const clientRect = this.refScroll.getBoundingClientRect()
refLoadingPlaceholder.setAttribute(
'style',
`position:fixed; width:${clientRect.width}px; height:${clientRect.height}px`,
)
this.refScroll.insertBefore(refLoadingPlaceholder, this.refScroll.firstChild)
this.refLoadingPlaceholder = refLoadingPlaceholder
}
this.refScroll.insertBefore(refLoadingPlaceholder, this.refScroll.firstChild)
this.refLoadingPlaceholder = refLoadingPlaceholder
}
// 创建底部填充块
createUnderPlaceholder() {
const refUnderPlaceholder = document.createElement('div')
refUnderPlaceholder.setAttribute('id', 'refUnderPlaceholder')
this.refScroll.appendChild(refUnderPlaceholder)
this.refUnderPlaceholder = refUnderPlaceholder
}
// 创建顶部填充块
createUpperPlaceholder() {
const refUpperPlaceholder = document.createElement('div')
refUpperPlaceholder.setAttribute('id', 'refUpperPlaceholder')
this.refScroll.insertBefore(refUpperPlaceholder, this.refScroll.firstChild)
this.refUpperPlaceholder = refUpperPlaceholder
}
// 创建底部填充块
createUnderPlaceholder() {
const refUnderPlaceholder = document.createElement('div')
refUnderPlaceholder.setAttribute('id', 'refUnderPlaceholder')
this.refScroll.appendChild(refUnderPlaceholder)
this.refUnderPlaceholder = refUnderPlaceholder
}
// 创建顶部填充块
createUpperPlaceholder() {
const refUpperPlaceholder = document.createElement('div')
refUpperPlaceholder.setAttribute('id', 'refUpperPlaceholder')
this.refScroll.insertBefore(refUpperPlaceholder, this.refScroll.firstChild)
this.refUpperPlaceholder = refUpperPlaceholder
}
scrollToPage = (...args) => {
const { pageSize } = this.props
const { rowHeight } = this.state
const [page] = args
this.refScroll.scrollTop = (page - 1) * pageSize * rowHeight + 1 // Bug fix: + 1个像素,点击页码向后翻页时存在少一个像素就变成上一页的bug
this.isPaginationClick = true
this.props.pagination && this.props.pagination.onChange && this.props.pagination.onChange(...args)
}
updateTable = () => {
const { clientHeight: tableHeight } = this.refTable
const { scrollTop } = this.refScroll
let { rowHeight, maxPage } = this.state
const { pageSize, total, debug } = this.props
scrollToPage = (...args) => {
const { pageSize } = this.props
const { rowHeight } = this.state
const [page] = args
this.refScroll.scrollTop = (page - 1) * pageSize * rowHeight + 1 // Bug fix: + 1个像素,点击页码向后翻页时存在少一个像素就变成上一页的bug
this.isPaginationClick = true
this.props.pagination && this.props.pagination.onChange && this.props.pagination.onChange(...args)
}
updateTable = () => {
const { clientHeight: tableHeight } = this.refTable
const { scrollTop } = this.refScroll
let { rowHeight, maxPage } = this.state
const { pageSize, total, debug } = this.props
if (this.isInitial) {
// 还在初始状态
maxPage = Math.ceil(total / pageSize)
const {
dataSource: { length },
} = this.state
rowHeight = tableHeight / length
if (rowHeight) {
// 当行高出现,表示初次呈现数据数时
this.isInitial = false
this.initialReslove()
}
}
let currentPage = Math.floor(scrollTop / (pageSize * rowHeight)) + 1 || 1
currentPage = currentPage > maxPage ? maxPage : currentPage
if (this.isInitial) {
// 还在初始状态
maxPage = Math.ceil(total / pageSize)
const {
dataSource: { length },
} = this.state
rowHeight = tableHeight / length
if (rowHeight) {
// 当行高出现,表示初次呈现数据数时
this.isInitial = false
this.initialReslove()
}
}
let currentPage = Math.floor(scrollTop / (pageSize * rowHeight)) + 1 || 1
currentPage = currentPage > maxPage ? maxPage : currentPage
debug &&
console.log('updateTable', {
currentPage,
})
this.setState(
{
direction: this.refScroll.scrollTop - this.state.scrollTop < 0 ? 'up' : 'down',
scrollTop: this.refScroll.scrollTop,
maxPage,
currentPage,
rowHeight,
},
// () => console.log('computeState done', this.state),
)
}
toggleObserver(condition = true) {
if (condition) {
this.io.observe(this.refUpperPlaceholder)
this.io.observe(this.refUnderPlaceholder)
this.io.observe(this.refTable)
this.refPageBoundaryBefore && this.io.observe(this.refPageBoundaryBefore)
this.refPageBoundaryAfter && this.io.observe(this.refPageBoundaryAfter)
} else {
this.io.unobserve(this.refUpperPlaceholder)
this.io.unobserve(this.refUnderPlaceholder)
this.io.unobserve(this.refTable)
this.refPageBoundaryBefore && this.io.unobserve(this.refPageBoundaryBefore)
this.refPageBoundaryAfter && this.io.unobserve(this.refPageBoundaryAfter)
}
}
render() {
const {
pageSize,
loadingIndicator,
loading,
total,
columns,
debug,
forwardedRef,
pagination,
...rest
} = this.props
debug &&
console.log('updateTable', {
currentPage,
})
this.setState(
{
direction: this.refScroll.scrollTop - this.state.scrollTop < 0 ? 'up' : 'down',
scrollTop: this.refScroll.scrollTop,
maxPage,
currentPage,
rowHeight,
},
// () => console.log('computeState done', this.state),
)
}
toggleObserver(condition = true) {
if (condition) {
this.io.observe(this.refUpperPlaceholder)
this.io.observe(this.refUnderPlaceholder)
this.io.observe(this.refTable)
this.refPageBoundaryBefore && this.io.observe(this.refPageBoundaryBefore)
this.refPageBoundaryAfter && this.io.observe(this.refPageBoundaryAfter)
} else {
this.io.unobserve(this.refUpperPlaceholder)
this.io.unobserve(this.refUnderPlaceholder)
this.io.unobserve(this.refTable)
this.refPageBoundaryBefore && this.io.unobserve(this.refPageBoundaryBefore)
this.refPageBoundaryAfter && this.io.unobserve(this.refPageBoundaryAfter)
}
}
render() {
const { pageSize, loadingIndicator, loading, total, columns, debug, forwardedRef, pagination, ...rest } = this.props
const { dataSource, upperHeight, underHeight, cacheData, currentPage } = this.state
const { dataSource, upperHeight, underHeight, cacheData, currentPage } = this.state
this.fullLoading = !cacheData[currentPage]
const { fullLoading } = this
debug && console.log('%c Rendering', 'color:#f00;font-weight:bold')
this.fullLoading = !cacheData[currentPage]
const { fullLoading } = this
debug && console.log('%c Rendering', 'color:#f00;font-weight:bold')
return (
<Fragment>
<InfinityTable.LoadingPlaceHolder
domNode={this.refLoadingPlaceholder}
loading={fullLoading}
loadingIndicator={<Spin tip="Loading..." />}
/>
<InfinityTable.PlaceHolder
height={upperHeight}
domNode={this.refUpperPlaceholder}
loading={loading && !fullLoading}
loadingIndicator={loadingIndicator}
/>
<InfinityTable.PlaceHolder
height={underHeight}
domNode={this.refUnderPlaceholder}
loading={loading && !fullLoading}
loadingIndicator={loadingIndicator}
/>
{total && pagination && ['top', 'both'].includes(pagination.position) && (
<Pagination
showQuickJumper
{...pagination}
onChange={this.scrollToPage}
current={currentPage}
pageSize={pageSize}
showSizeChanger={false}
total={total}
className={`infinity-page-table-pagination ${
pagination && pagination.className ? pagination.className : ''
}`}
/>
)}
<Table
rowKey={record => record.key}
{...rest}
ref={forwardedRef}
columns={columns}
dataSource={dataSource}
pagination={false}
className={`infinity-page-table ${rest.className ? rest.className : ''}`}
/>
{total && pagination && [undefined, 'bottom', 'both'].includes(pagination.position) && (
<Pagination
showQuickJumper
{...pagination}
onChange={this.scrollToPage}
current={currentPage}
pageSize={pageSize}
showSizeChanger={false}
total={total}
className={`infinity-page-table-pagination ${
pagination && pagination.className ? pagination.className : ''
}`}
/>
)}
</Fragment>
)
}
return (
<Fragment>
<InfinityTable.LoadingPlaceHolder
domNode={this.refLoadingPlaceholder}
loading={fullLoading}
loadingIndicator={<Spin tip="Loading..." />}
/>
<InfinityTable.PlaceHolder
height={upperHeight}
domNode={this.refUpperPlaceholder}
loading={loading && !fullLoading}
loadingIndicator={loadingIndicator}
/>
<InfinityTable.PlaceHolder
height={underHeight}
domNode={this.refUnderPlaceholder}
loading={loading && !fullLoading}
loadingIndicator={loadingIndicator}
/>
{total && pagination && ['top', 'both'].includes(pagination.position) && (
<Pagination
showQuickJumper
{...pagination}
onChange={this.scrollToPage}
current={currentPage}
pageSize={pageSize}
showSizeChanger={false}
total={total}
className={`infinity-page-table-pagination ${
pagination && pagination.className ? pagination.className : ''
}`}
/>
)}
<Table
rowKey={record => record.key}
{...rest}
ref={forwardedRef}
columns={columns}
dataSource={dataSource}
pagination={false}
className={`infinity-page-table ${rest.className ? rest.className : ''}`}
/>
{total && pagination && [undefined, 'bottom', 'both'].includes(pagination.position) && (
<Pagination
showQuickJumper
{...pagination}
onChange={this.scrollToPage}
current={currentPage}
pageSize={pageSize}
showSizeChanger={false}
total={total}
className={`infinity-page-table-pagination ${
pagination && pagination.className ? pagination.className : ''
}`}
/>
)}
</Fragment>
)
}
}
InfinityTable.defaultProps = {
// loading 效果, A visual react component for Loading status
loadingIndicator: (
<div
style={{
textAlign: 'center',
paddingTop: 20,
paddingBottom: 20,
border: '1px solid #e8e8e8',
}}
>
<Spin tip="Loading..." />
</div>
),
pagination: { defaultCurrent: 1 }, // 分页器
onScroll: null, // 滚动事件
onFetch: noop, // 滚动到低部触发Fetch方法
bidirectionalCachePages: Infinity, // 当前页前后的缓存页码数量,默认为无限
total: 0, // 总共数据条数
debug: false, // display console log for debug
loading: false, // 是否loading状态
pageSize: 30, // 每次Loading数据量,pageSize * 3 = 最大真实DOM大小,Reality DOM row count
// loading 效果, A visual react component for Loading status
loadingIndicator: (
<div
style={{
textAlign: 'center',
paddingTop: 20,
paddingBottom: 20,
border: '1px solid #e8e8e8',
}}
>
<Spin tip="Loading..." />
</div>
),
pagination: { defaultCurrent: 1 }, // 分页器
onScroll: null, // 滚动事件
onFetch: noop, // 滚动到低部触发Fetch方法
bidirectionalCachePages: Infinity, // 当前页前后的缓存页码数量,默认为无限
total: 0, // 总共数据条数
debug: false, // display console log for debug
loading: false, // 是否loading状态
pageSize: 30, // 每次Loading数据量,pageSize * 3 = 最大真实DOM大小,Reality DOM row count
}
InfinityTable.propTypes = {
// loading 效果
className: string,
loadingIndicator: element,
onScroll: func, // 滚动事件
pagination: oneOfType([
bool,
shape({
className: string,
position: oneOf(['both', 'top', 'bottom']),
className: string,
defaultCurrent: number,
hideOnSinglePage: bool,
itemRender: func,
showQuickJumper: bool,
showTotal: func,
simple: bool,
size: string,
onChange: func,
}),
]),
onFetch: func.isRequired, // 滚动触发Fetch方法
pageSize: number.isRequired,
bidirectionalCachePages: number.isRequired,
total: number.isRequired,
dataSource: array.isRequired,
columns: array.isRequired,
forwardedRef: object,
debug: bool,
loading: bool.isRequired,
// loading 效果
className: string,
loadingIndicator: element,
onScroll: func, // 滚动事件
pagination: oneOfType([
bool,
shape({
className: string,
position: oneOf(['both', 'top', 'bottom']),
className: string,
defaultCurrent: number,
hideOnSinglePage: bool,
itemRender: func,
showQuickJumper: bool,
showTotal: func,
simple: bool,
size: string,
onChange: func,
}),
]),
onFetch: func.isRequired, // 滚动触发Fetch方法
pageSize: number.isRequired,
bidirectionalCachePages: number.isRequired,
total: number.isRequired,
dataSource: array.isRequired,
columns: array.isRequired,
forwardedRef: object,
debug: bool,
loading: bool.isRequired,
}

@@ -593,0 +577,0 @@

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc