1
1
<script setup lang="ts">
2
2
import type { TimelineEvent } from ' @vue/devtools-kit'
3
3
import { computed } from ' vue'
4
+ import { RecycleScroller } from ' vue-virtual-scroller'
4
5
import { formatTime } from ' ~/utils'
6
+ import ' vue-virtual-scroller/dist/vue-virtual-scroller.css'
5
7
6
8
const props = defineProps <{
7
- data: Array <TimelineEvent [' event' ] & { color? : string }>
9
+ data: Array <TimelineEvent [' event' ] & { color? : string , id ? : number }>
8
10
}>()
9
11
10
12
const selected = defineModel ()
@@ -13,12 +15,13 @@ const colors = ['#3e5770', '#42b983', '#0098c4']
13
15
const normalizedData = computed (() => {
14
16
let currentColorIndex = - 1
15
17
let currentGroupId = 0
16
- props .data .forEach ((item ) => {
18
+ props .data .forEach ((item , index ) => {
17
19
if (item .groupId !== currentGroupId || currentColorIndex === - 1 )
18
20
currentColorIndex = (currentColorIndex + 1 ) % colors .length
19
21
20
22
currentGroupId = item .groupId ?? currentGroupId
21
23
24
+ item .id = index
22
25
item .color = colors [currentColorIndex ]
23
26
})
24
27
return props .data
@@ -27,19 +30,28 @@ const normalizedData = computed(() => {
27
30
28
31
<template >
29
32
<div class =" p3" >
30
- <ul >
31
- <li v-for =" (item, index) in normalizedData" :key =" index" class =" relative mb7 h6 cursor-pointer" :style =" { color: selected === index ? item.color : '' }" @click =" selected = index" >
33
+ <RecycleScroller
34
+ v-slot =" { item }"
35
+ :items =" normalizedData"
36
+ :min-item-size =" 52"
37
+ key-field =" id"
38
+ page-mode
39
+ item-tag =" li"
40
+ list-tag =" ul"
41
+ :buffer =" 20"
42
+ >
43
+ <div class =" relative mb7 h6 cursor-pointer" :style =" { color: selected === item.id ? item.color : '' }" @click =" selected = item.id" >
32
44
<!-- head -->
33
45
<span class =" absolute top-1.5 inline-block h3 w3 b rounded-50%" :style =" { border: `3px solid ${item.color}` }" />
34
46
<!-- line -->
35
- <span v-if =" index < data.length - 1" class =" absolute left-5px top-4.5 h10 w0 border-l-2" border =" solid gray2" />
47
+ <span v-if =" item.id < data.length - 1" class =" absolute left-5px top-4.5 h10 w0 border-l-2" border =" solid gray2" />
36
48
<!-- content -->
37
49
<p class =" h-full flex items-center truncate pl5" >
38
50
<span absolute top-5 pr2 text-3 op40 >[{{ formatTime(item.time) }}]</span >
39
51
{{ item.title }}
40
52
<span pl2 op30 >{{ item.subtitle }}</span >
41
53
</p >
42
- </li >
43
- </ul >
54
+ </div >
55
+ </RecycleScroller >
44
56
</div >
45
57
</template >
0 commit comments