Skip to content

Commit 40b050d

Browse files
committed
chore: small changes
1 parent 449925e commit 40b050d

File tree

4 files changed

+56
-44
lines changed

4 files changed

+56
-44
lines changed

src/virtual-list/README.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,14 @@ Append item.
4949

5050
Clear all items.
5151

52+
### remove(el: HTMLElement): void
53+
54+
Remove item.
55+
5256
### setItems(els: HTMLElement[]): void
5357

5458
Set items.
5559

56-
### update(): void
60+
### update(el?: HTMLElement): void
5761

58-
Recalculate all heights.
62+
Update heights.

src/virtual-list/index.ts

+40-38
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ import $ from 'licia/$'
33
import throttle from 'licia/throttle'
44
import isHidden from 'licia/isHidden'
55
import now from 'licia/now'
6-
import ResizeSensor from 'licia/ResizeSensor'
76
import isEmpty from 'licia/isEmpty'
8-
import map from 'licia/map'
97
import each from 'licia/each'
108
import clone from 'licia/clone'
119
import some from 'licia/some'
@@ -69,35 +67,45 @@ export default class VirtualList extends Component<IOptions> {
6967
/** Clear all items. */
7068
clear() {
7169
this.items = []
72-
this.el.textContent = ''
70+
this.render()
7371
}
7472
/** Append item. */
7573
append(el: HTMLElement) {
76-
const item = new Item(el, this.el)
74+
const item: Item = (el as any).virtualListItem || new Item(el)
7775
this.items.push(item)
78-
this.updateSize(item)
76+
this.update(el)
7977
}
8078
/** Set items. */
8179
setItems(els: HTMLElement[]) {
82-
each(this.items, (item) => item.destroy())
83-
this.items = map(els, (el) => new Item(el, this.el))
8480
this.updateItems = []
81+
each(els, el => this.append(el))
8582
}
86-
/** Recalculate all heights. */
87-
update() {
88-
this.updateSize()
83+
/** Remove item. */
84+
remove(el: HTMLElement) {
85+
const item = (el as any).virtualListItem
86+
if (!item) {
87+
return
88+
}
89+
const idx = this.items.indexOf(item)
90+
if (idx === -1) {
91+
return
92+
}
93+
this.items.splice(idx, 1)
94+
item.destroy()
95+
this.render()
8996
}
90-
private updateSize(item?: Item) {
91-
if (item) {
92-
this.updateItems.push(item)
97+
/** Update heights. */
98+
update(el?: HTMLElement) {
99+
if (el) {
100+
this.updateItems.push((el as any).virtualListItem)
93101
} else {
94102
this.updateItems = clone(this.items)
95103
}
96104
if (!this.updateTimer) {
97-
this._updateSize()
105+
this._update()
98106
}
99107
}
100-
private _updateSize = () => {
108+
private _update = () => {
101109
const items = this.updateItems.splice(0, 1000)
102110
if (isEmpty(items)) {
103111
return
@@ -111,14 +119,14 @@ export default class VirtualList extends Component<IOptions> {
111119
}
112120
fakeEl.appendChild(fakeFrag)
113121
for (let i = 0; i < len; i++) {
114-
items[i].updateSize()
122+
items[i].update()
115123
}
116124
fakeEl.textContent = ''
117125

118126
this.render()
119127

120128
if (!isEmpty(this.updateItems)) {
121-
this.updateTimer = setTimeout(() => this._updateSize(), 100)
129+
this.updateTimer = setTimeout(() => this._update(), 16)
122130
} else {
123131
this.updateTimer = null
124132
}
@@ -165,7 +173,7 @@ export default class VirtualList extends Component<IOptions> {
165173
let topSpaceHeight = 0
166174
let bottomSpaceHeight = 0
167175
let currentHeight = 0
168-
let currentWidth = this.spaceWidth
176+
let currentWidth = 0
169177

170178
const len = items.length
171179

@@ -193,7 +201,10 @@ export default class VirtualList extends Component<IOptions> {
193201
this.updateTopSpace(topSpaceHeight)
194202
this.updateBottomSpace(bottomSpaceHeight)
195203

196-
if (!some(displayItems, (item, idx) => item !== this.displayItems[idx])) {
204+
if (
205+
len > 0 &&
206+
!some(displayItems, (item, idx) => item !== this.displayItems[idx])
207+
) {
197208
return
198209
}
199210

@@ -209,22 +220,23 @@ export default class VirtualList extends Component<IOptions> {
209220
const { scrollHeight } = container
210221
if (this.isAtBottom && scrollTop <= scrollHeight - offsetHeight) {
211222
container.scrollTop = 10000000
223+
this.render()
212224
}
213225
}
214226
},
215227
16
216228
)
217229
private onScroll = () => {
218-
const { scrollHeight, offsetHeight, scrollTop } = this
230+
const { scrollHeight, clientHeight, scrollTop } = this
219231
.container as HTMLElement
220232
// safari bounce effect
221233
if (scrollTop <= 0) return
222-
if (offsetHeight + scrollTop > scrollHeight) return
234+
if (clientHeight + scrollTop > scrollHeight) return
223235

224236
let isAtBottom = false
225-
if (scrollHeight === offsetHeight) {
237+
if (scrollHeight === clientHeight) {
226238
isAtBottom = true
227-
} else if (Math.abs(scrollHeight - offsetHeight - scrollTop) < 1) {
239+
} else if (Math.abs(scrollHeight - clientHeight - scrollTop) < 1) {
228240
isAtBottom = true
229241
}
230242
this.isAtBottom = isAtBottom
@@ -262,7 +274,7 @@ export default class VirtualList extends Component<IOptions> {
262274
if (
263275
this.topSpaceHeight < scrollTop - topTolerance &&
264276
this.topSpaceHeight + this.el.offsetHeight >
265-
scrollTop + offsetHeight + bottomTolerance
277+
scrollTop + clientHeight + bottomTolerance
266278
) {
267279
return
268280
}
@@ -285,26 +297,16 @@ class Item {
285297
el: HTMLElement
286298
width: number
287299
height: number
288-
private resizeSensor: ResizeSensor
289-
constructor(el: HTMLElement, container: HTMLElement) {
300+
constructor(el: HTMLElement) {
290301
this.el = el
302+
;(el as any).virtualListItem = this
291303
this.width = 0
292304
this.height = 0
293-
294-
this.resizeSensor = new ResizeSensor(el)
295-
this.resizeSensor.addListener(() => {
296-
if (el.parentNode === container) {
297-
this.updateSize()
298-
}
299-
})
300305
}
301306
destroy() {
302-
this.resizeSensor.destroy()
307+
delete (this.el as any).virtualListItem
303308
}
304-
updateSize() {
305-
if (isHidden(this.el)) {
306-
return
307-
}
309+
update() {
308310
const { width, height } = this.el.getBoundingClientRect()
309311
this.width = width
310312
this.height = height

src/virtual-list/story.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import random from 'licia/random'
99
import randomColor from 'licia/randomColor'
1010
import readme from './README.md'
1111
import randomId from 'licia/randomId'
12-
import { button } from '@storybook/addon-knobs'
12+
import { boolean, button } from '@storybook/addon-knobs'
1313

1414
const def = story(
1515
'virtual-list',
@@ -26,7 +26,11 @@ const def = story(
2626
const container = h('div')
2727
wrapper.appendChild(container)
2828

29-
const virtualList = new VirtualList(container)
29+
const autoScroll = boolean('Auto scroll', false)
30+
31+
const virtualList = new VirtualList(container, {
32+
autoScroll,
33+
})
3034

3135
function randomItems(count) {
3236
const items = []
@@ -38,10 +42,10 @@ const def = story(
3842
{
3943
style: {
4044
color: '#fff',
41-
width: '100%',
4245
background: randomColor({ lightness: 0.5 }),
4346
minHeight: random(30, 100) + 'px',
4447
lineHeight: '1.5em',
48+
textWrap: 'nowrap',
4549
},
4650
},
4751
toStr(i) + ' ' + randomId(random(30, 1000))

src/virtual-list/style.scss

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99

1010
.fake-items {
1111
position: absolute;
12-
left: 0;
1312
top: 0;
13+
left: 0;
1414
pointer-events: none;
1515
visibility: hidden;
1616
}
1717

1818
.items {
1919
position: absolute;
20+
top: 0;
21+
left: 0;
2022
}

0 commit comments

Comments
 (0)