Skip to content

Commit

Permalink
perf(data-grid): append a lot
Browse files Browse the repository at this point in the history
  • Loading branch information
surunzi committed Nov 14, 2024
1 parent 16f0ce3 commit c804b8b
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 39 deletions.
61 changes: 46 additions & 15 deletions src/data-grid/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ export interface IDataGridNodeOptions {
selectable?: boolean
}

const MIN_APPEND_INTERVAL = 100

/**
* Grid for displaying datasets.
*
Expand Down Expand Up @@ -102,11 +104,14 @@ export default class DataGrid extends Component<IOptions> {
private onResize: () => void
private tableBody: HTMLElement
private nodes: DataGridNode[] = []
private displayNodes: DataGridNode[] = []
private colWidthsInitialized = false
private colMap: types.PlainObj<IColumn> = {}
private sortId?: string
private selectedNode: DataGridNode | null = null
private isAscending = true
private appendTimer: NodeJS.Timeout | null = null
private frag: DocumentFragment = document.createDocumentFragment()
private colWidths: number[] = []
constructor(container: HTMLElement, options: IOptions) {
super(container, { compName: 'data-grid' }, options)
Expand Down Expand Up @@ -179,21 +184,34 @@ export default class DataGrid extends Component<IOptions> {
const node = new DataGridNode(this, data, options)
this.nodes.push(node)

const isVisible = this.filterNode(node)
if (isVisible) {
this.displayNodes.push(node)
}

if (this.sortId) {
this.sortNodes(this.sortId, this.isAscending)
} else {
if (this.filterNode(node)) {
this.tableBody.insertBefore(node.container, this.fillerRow)
this.updateHeight()
if (isVisible) {
this.frag.appendChild(node.container)
if (!this.appendTimer) {
this.appendTimer = setTimeout(this._append, MIN_APPEND_INTERVAL)
}
}
}

return node
}
private _append = () => {
this.tableBody.insertBefore(this.frag, this.fillerRow)
this.appendTimer = null
this.updateHeight()
}
/** Clear all data. */
clear() {
each(this.nodes, (node) => node.detach())
this.detachAll()
this.nodes = []
this.displayNodes = []
this.selectNode(null)

this.updateHeight()
Expand Down Expand Up @@ -366,6 +384,15 @@ export default class DataGrid extends Component<IOptions> {
this.updateHeight()
break
case 'filter':
this.displayNodes = []
each(this.nodes, (node) => {
if (this.filterNode(node)) {
this.displayNodes.push(node)
}
})
if (this.selectedNode && !this.filterNode(this.selectedNode)) {
this.selectNode(null)
}
this.renderData()
break
}
Expand All @@ -375,7 +402,7 @@ export default class DataGrid extends Component<IOptions> {
const column = this.colMap[id]

const comparator = column.comparator || naturalOrderComparator
this.nodes.sort(function (a, b) {
function sortFn(a: DataGridNode, b: DataGridNode) {
let aVal = a.data[id]
let bVal = b.data[id]
if (isEl(aVal)) {
Expand All @@ -386,7 +413,9 @@ export default class DataGrid extends Component<IOptions> {
}

return isAscending ? comparator(aVal, bVal) : comparator(bVal, aVal)
})
}
this.nodes.sort(sortFn)
this.displayNodes.sort(sortFn)

this.renderData()

Expand Down Expand Up @@ -460,20 +489,22 @@ export default class DataGrid extends Component<IOptions> {
}
}
private renderData() {
const { tableBody, nodes, fillerRow } = this
const { tableBody, displayNodes, fillerRow } = this

each(nodes, (node) => node.detach())
each(nodes, (node) => {
if (this.filterNode(node)) {
tableBody.insertBefore(node.container, fillerRow)
}
this.detachAll()
const frag = document.createDocumentFragment()
each(displayNodes, (node) => {
frag.appendChild(node.container)
})
if (this.selectedNode && !this.filterNode(this.selectedNode)) {
this.selectNode(null)
}
tableBody.insertBefore(frag, fillerRow)

this.updateHeight()
}
private detachAll() {
const { tableBody } = this
tableBody.innerHTML = ''
tableBody.appendChild(this.fillerRow)
}
private filterNode(node: DataGridNode) {
let { filter } = this.options

Expand Down
49 changes: 25 additions & 24 deletions src/data-grid/story.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import { object, number, button, text } from '@storybook/addon-knobs'
const def = story(
'data-grid',
(container) => {
const { columns, maxHeight, minHeight, filter } = createKnobs()
const { maxHeight, minHeight, filter } = createKnobs()

const dataGrid = new DataGrid(container, {
columns,
columns: getColumns(),
maxHeight,
minHeight,
filter,
Expand Down Expand Up @@ -44,7 +44,7 @@ const def = story(
changelog,
source: __STORY__,
ReactComponent() {
const { columns, minHeight, maxHeight, filter } = createKnobs()
const { minHeight, maxHeight, filter } = createKnobs()

return (
<LunaDataGrid
Expand All @@ -54,7 +54,7 @@ const def = story(
onDeselect={() => {
console.log('deselect')
}}
columns={columns}
columns={getColumns()}
minHeight={minHeight}
maxHeight={maxHeight}
filter={filter}
Expand All @@ -65,6 +65,27 @@ const def = story(
}
)

function getColumns() {
return [
{
id: 'index',
title: 'Index',
weight: 20,
sortable: true,
},
{
id: 'name',
title: 'Name',
sortable: true,
weight: 30,
},
{
id: 'site',
title: 'Site',
},
]
}

function getData() {
return [
{
Expand Down Expand Up @@ -111,25 +132,6 @@ function getData() {
}

function createKnobs() {
const columns = object('Columns', [
{
id: 'index',
title: 'Index',
weight: 20,
sortable: true,
},
{
id: 'name',
title: 'Name',
sortable: true,
weight: 30,
},
{
id: 'site',
title: 'Site',
},
])

const minHeight = number('Min Height', 80, {
range: true,
min: 23,
Expand All @@ -144,7 +146,6 @@ function createKnobs() {
const filter = text('Filter', '')

return {
columns,
minHeight,
maxHeight,
filter,
Expand Down

0 comments on commit c804b8b

Please sign in to comment.