Skip to content

Commit fd58a95

Browse files
ktsnAkryum
andauthored
fix: avoid jumping scroll position when upper item size is calculated (#374)
Co-authored-by: Guillaume Chau <[email protected]>
1 parent c63129f commit fd58a95

File tree

2 files changed

+30
-9
lines changed

2 files changed

+30
-9
lines changed

docs-src/src/components/TestChat.vue

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
<button @click="addItems(10)">
1111
Add 10 items
1212
</button>
13+
<button @click="addItems(50)">
14+
Add 50 items
15+
</button>
1316
</div>
1417

1518
<DynamicScroller
@@ -25,12 +28,7 @@
2528
:active="active"
2629
:data-index="index"
2730
>
28-
<div
29-
class="message"
30-
:style="{
31-
height: `${item.size}px`,
32-
}"
33-
>
31+
<div class="message">
3432
{{ item.text }}
3533
</div>
3634
</DynamicScrollerItem>
@@ -54,9 +52,8 @@ export default {
5452
addItems (count = 1) {
5553
for (let i = 0; i < count; i++) {
5654
this.items.push({
57-
text: faker.lorem.sentence(),
55+
text: faker.lorem.lines(),
5856
id: this.items.length + 1,
59-
size: Math.random() * 120 + 40,
6057
})
6158
}
6259
this.scrollToBottom()

src/components/DynamicScroller.vue

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,33 @@ export default {
140140
direction (value) {
141141
this.forceUpdate(true)
142142
},
143+
144+
itemsWithSize (next, prev) {
145+
const scrollTop = this.$el.scrollTop
146+
147+
// Calculate total diff between prev and next sizes
148+
// over current scroll top. Then add it to scrollTop to
149+
// avoid jumping the contents that the user is seeing.
150+
let prevActiveTop = 0; let activeTop = 0
151+
const length = Math.min(next.length, prev.length)
152+
for (let i = 0; i < length; i++) {
153+
if (prevActiveTop >= scrollTop) {
154+
break
155+
}
156+
prevActiveTop += prev[i].size || this.minItemSize
157+
activeTop += next[i].size || this.minItemSize
158+
}
159+
const offset = activeTop - prevActiveTop
160+
161+
if (offset === 0) {
162+
return
163+
}
164+
165+
this.$el.scrollTop += offset
166+
},
143167
},
144168
145-
created () {
169+
beforeCreate () {
146170
this.$_updates = []
147171
this.$_undefinedSizes = 0
148172
this.$_undefinedMap = {}

0 commit comments

Comments
 (0)