Skip to content

Commit 449925e

Browse files
committed
chore: small changes
1 parent 9357dec commit 449925e

File tree

3 files changed

+81
-30
lines changed

3 files changed

+81
-30
lines changed

src/virtual-list/README.md

+18
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,21 @@ virtualList.append(document.createElement('div'))
3838
## Configuration
3939

4040
* autoScroll(boolean): Auto scroll if at bottom.
41+
42+
## Api
43+
44+
### append(el: HTMLElement): void
45+
46+
Append item.
47+
48+
### clear(): void
49+
50+
Clear all items.
51+
52+
### setItems(els: HTMLElement[]): void
53+
54+
Set items.
55+
56+
### update(): void
57+
58+
Recalculate all heights.

src/virtual-list/index.ts

+45-27
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import isHidden from 'licia/isHidden'
55
import now from 'licia/now'
66
import ResizeSensor from 'licia/ResizeSensor'
77
import isEmpty from 'licia/isEmpty'
8-
import unique from 'licia/unique'
98
import map from 'licia/map'
10-
import debounce from 'licia/debounce'
119
import each from 'licia/each'
10+
import clone from 'licia/clone'
11+
import some from 'licia/some'
1212

1313
/** IOptions */
1414
export interface IOptions extends IComponentOptions {
@@ -34,6 +34,7 @@ export default class VirtualList extends Component<IOptions> {
3434
private $space: $.$
3535
private space: HTMLElement
3636
private spaceHeight = 0
37+
private spaceWidth = 0
3738
private topSpaceHeight = 0
3839
// @ts-ignore
3940
private bottomSpaceHeight = 0
@@ -45,7 +46,7 @@ export default class VirtualList extends Component<IOptions> {
4546
private isAtBottom = true
4647
private updateTimer: NodeJS.Timeout | null = null
4748
private updateItems: Item[] = []
48-
private resizeSensor: ResizeSensor
49+
private displayItems: Item[] = []
4950
private scrollTimer: NodeJS.Timeout | null = null
5051
constructor(container: HTMLElement, options: IOptions = {}) {
5152
super(container, { compName: 'virtual-list' }, options)
@@ -63,34 +64,35 @@ export default class VirtualList extends Component<IOptions> {
6364
this.$space = this.find('.items-space')
6465
this.space = this.$space.get(0) as HTMLElement
6566

66-
this.resizeSensor = new ResizeSensor(this.space)
67-
6867
this.bindEvent()
6968
}
69+
/** Clear all items. */
7070
clear() {
7171
this.items = []
72-
this.render()
72+
this.el.textContent = ''
7373
}
74+
/** Append item. */
7475
append(el: HTMLElement) {
7576
const item = new Item(el, this.el)
7677
this.items.push(item)
7778
this.updateSize(item)
7879
}
80+
/** Set items. */
7981
setItems(els: HTMLElement[]) {
8082
each(this.items, (item) => item.destroy())
8183
this.items = map(els, (el) => new Item(el, this.el))
8284
this.updateItems = []
83-
this.updateAllSize()
8485
}
85-
private updateAllSize = debounce(() => {
86-
this.updateItems.push(...this.items)
87-
this.updateItems = unique(this.updateItems)
88-
if (!this.updateTimer) {
89-
this._updateSize()
86+
/** Recalculate all heights. */
87+
update() {
88+
this.updateSize()
89+
}
90+
private updateSize(item?: Item) {
91+
if (item) {
92+
this.updateItems.push(item)
93+
} else {
94+
this.updateItems = clone(this.items)
9095
}
91-
}, 1000)
92-
private updateSize(item: Item) {
93-
this.updateItems.push(item)
9496
if (!this.updateTimer) {
9597
this._updateSize()
9698
}
@@ -135,17 +137,16 @@ export default class VirtualList extends Component<IOptions> {
135137
private updateBottomSpace(height: number) {
136138
this.bottomSpaceHeight = height
137139
}
138-
private updateSpace(height: number) {
139-
if (this.spaceHeight === height) return
140+
private updateSpace(height: number, width: number) {
141+
if (this.spaceHeight === height && this.spaceWidth === width) {
142+
return
143+
}
140144
this.spaceHeight = height
145+
this.spaceWidth = width
141146
this.space.style.height = height + 'px'
147+
this.space.style.width = width + 'px'
142148
}
143149
private bindEvent() {
144-
this.resizeSensor.addListener(
145-
throttle(() => {
146-
this.updateAllSize()
147-
}, 100)
148-
)
149150
this.$container.on('scroll', this.onScroll)
150151
}
151152
private render = throttle(
@@ -164,29 +165,43 @@ export default class VirtualList extends Component<IOptions> {
164165
let topSpaceHeight = 0
165166
let bottomSpaceHeight = 0
166167
let currentHeight = 0
168+
let currentWidth = this.spaceWidth
167169

168170
const len = items.length
169171

170-
const frag = document.createDocumentFragment()
172+
const displayItems = []
171173
for (let i = 0; i < len; i++) {
172174
const item = items[i]
173-
const { el, height } = item
175+
const { height, width } = item
174176

175177
if (currentHeight > bottom) {
176178
bottomSpaceHeight += height
177179
} else if (currentHeight + height > top) {
178-
frag.appendChild(el)
180+
displayItems.push(item)
179181
} else if (currentHeight < top) {
180182
topSpaceHeight += height
181183
}
182184

183185
currentHeight += height
186+
187+
if (currentWidth < width) {
188+
currentWidth = width
189+
}
184190
}
185191

186-
this.updateSpace(currentHeight)
192+
this.updateSpace(currentHeight, currentWidth)
187193
this.updateTopSpace(topSpaceHeight)
188194
this.updateBottomSpace(bottomSpaceHeight)
189195

196+
if (!some(displayItems, (item, idx) => item !== this.displayItems[idx])) {
197+
return
198+
}
199+
200+
const frag = document.createDocumentFragment()
201+
for (let i = 0, len = displayItems.length; i < len; i++) {
202+
frag.appendChild(displayItems[i].el)
203+
}
204+
190205
el.textContent = ''
191206
el.appendChild(frag)
192207

@@ -278,7 +293,7 @@ class Item {
278293

279294
this.resizeSensor = new ResizeSensor(el)
280295
this.resizeSensor.addListener(() => {
281-
if (el.parentNode === container && !isHidden(el)) {
296+
if (el.parentNode === container) {
282297
this.updateSize()
283298
}
284299
})
@@ -287,6 +302,9 @@ class Item {
287302
this.resizeSensor.destroy()
288303
}
289304
updateSize() {
305+
if (isHidden(this.el)) {
306+
return
307+
}
290308
const { width, height } = this.el.getBoundingClientRect()
291309
this.width = width
292310
this.height = height

src/virtual-list/story.js

+18-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import story from '../share/story'
44
import h from 'licia/h'
55
import toStr from 'licia/toStr'
66
import $ from 'licia/$'
7+
import each from 'licia/each'
78
import random from 'licia/random'
89
import randomColor from 'licia/randomColor'
910
import readme from './README.md'
@@ -28,8 +29,10 @@ const def = story(
2829
const virtualList = new VirtualList(container)
2930

3031
function randomItems(count) {
32+
const items = []
33+
3134
for (let i = 0; i < count; i++) {
32-
virtualList.append(
35+
items.push(
3336
h(
3437
'div',
3538
{
@@ -45,12 +48,24 @@ const def = story(
4548
)
4649
)
4750
}
51+
52+
return items
4853
}
4954

50-
randomItems(100)
55+
each(randomItems(100), (item) => virtualList.append(item))
5156

5257
button('Append 10000 items', () => {
53-
randomItems(10000)
58+
each(randomItems(10000), (item) => virtualList.append(item))
59+
return false
60+
})
61+
62+
button('Set 10000 items', () => {
63+
virtualList.setItems(randomItems(10000))
64+
return false
65+
})
66+
67+
button('Clear', () => {
68+
virtualList.clear()
5469
return false
5570
})
5671

0 commit comments

Comments
 (0)