File tree Expand file tree Collapse file tree 3 files changed +217
-7
lines changed Expand file tree Collapse file tree 3 files changed +217
-7
lines changed Original file line number Diff line number Diff line change 5
5
<span class =" package-name" >vue-virtual-scroller</span >
6
6
</span >
7
7
8
- <router-link :to =" { name: 'home' }" exact >Home</router-link >
9
- <router-link :to =" { name: 'recycle' }" >Recycle scroller</router-link >
10
- <router-link :to =" { name: 'dynamic' }" >Dynamic scroller</router-link >
11
- <router-link :to =" { name: 'horizontal' }" >Horizontal</router-link >
12
- <router-link :to =" { name: 'test-chat' }" >Scroll to bottom</router-link >
13
- <router-link :to =" { name: 'simple-list' }" >Simple array</router-link >
8
+ <router-link
9
+ :to =" { name: 'home' }"
10
+ exact
11
+ >
12
+ Home
13
+ </router-link >
14
+ <router-link :to =" { name: 'recycle' }" >
15
+ Recycle scroller
16
+ </router-link >
17
+ <router-link :to =" { name: 'dynamic' }" >
18
+ Dynamic scroller
19
+ </router-link >
20
+ <router-link :to =" { name: 'horizontal' }" >
21
+ Horizontal
22
+ </router-link >
23
+ <router-link :to =" { name: 'test-chat' }" >
24
+ Scroll to bottom
25
+ </router-link >
26
+ <router-link :to =" { name: 'simple-list' }" >
27
+ Simple array
28
+ </router-link >
29
+ <router-link :to =" { name: 'chat' }" >
30
+ Chat demo
31
+ </router-link >
14
32
</nav >
15
- <router-view class =" page" />
33
+ <router-view class =" page" />
16
34
</div >
17
35
</template >
18
36
Original file line number Diff line number Diff line change
1
+ <template >
2
+ <div class =" chat-demo" >
3
+ <div class =" toolbar" >
4
+ <button
5
+ v-if =" !streaming"
6
+ @click =" startStream()"
7
+ >
8
+ Start stream
9
+ </button >
10
+ <button
11
+ v-else
12
+ @click =" stopStream()"
13
+ >
14
+ Stop stream
15
+ </button >
16
+
17
+ <input
18
+ v-model =" search"
19
+ placeholder =" Filter..."
20
+ >
21
+ </div >
22
+
23
+ <DynamicScroller
24
+ ref =" scroller"
25
+ :items =" filteredItems"
26
+ :min-item-size =" 54"
27
+ class =" scroller"
28
+ >
29
+ <template #before >
30
+ <div class =" notice" >
31
+ The message heights are unknown.
32
+ </div >
33
+ </template >
34
+
35
+ <template v-slot =" { item , index , active } " >
36
+ <DynamicScrollerItem
37
+ :item =" item"
38
+ :active =" active"
39
+ :size-dependencies =" [
40
+ item.message,
41
+ ]"
42
+ :data-index =" index"
43
+ :data-active =" active"
44
+ :title =" `Click to change message ${index}`"
45
+ class =" message"
46
+ @click.native =" changeMessage(item)"
47
+ >
48
+ <div class =" avatar" >
49
+ <img
50
+ :key =" item.avatar"
51
+ :src =" item.avatar"
52
+ alt =" avatar"
53
+ class =" image"
54
+ >
55
+ </div >
56
+ <div class =" text" >
57
+ {{ item.message }}
58
+ </div >
59
+ <div class =" index" >
60
+ <span >{{ item.id }} (id)</span >
61
+ <span >{{ index }} (index)</span >
62
+ </div >
63
+ </DynamicScrollerItem >
64
+ </template >
65
+ </DynamicScroller >
66
+ </div >
67
+ </template >
68
+
69
+ <script >
70
+ import { generateMessage } from ' ../data'
71
+
72
+ let id = 0
73
+
74
+ const messages = []
75
+ for (let i = 0 ; i < 10000 ; i++ ) {
76
+ messages .push (generateMessage ())
77
+ }
78
+
79
+ export default {
80
+ data () {
81
+ return {
82
+ items: [],
83
+ search: ' ' ,
84
+ streaming: false ,
85
+ }
86
+ },
87
+
88
+ computed: {
89
+ filteredItems () {
90
+ const { search , items } = this
91
+ if (! search) return items
92
+ const lowerCaseSearch = search .toLowerCase ()
93
+ return items .filter (i => i .message .toLowerCase ().includes (lowerCaseSearch))
94
+ },
95
+ },
96
+
97
+ destroyed () {
98
+ this .stopStream ()
99
+ },
100
+
101
+ methods: {
102
+ changeMessage (message ) {
103
+ Object .assign (message, generateMessage ())
104
+ },
105
+
106
+ addMessage () {
107
+ this .items .push ({
108
+ id: id++ ,
109
+ ... messages[id % 10000 ],
110
+ })
111
+ this .scrollToBottom ()
112
+
113
+ if (this .streaming ) {
114
+ requestAnimationFrame (this .addMessage )
115
+ }
116
+ },
117
+
118
+ scrollToBottom () {
119
+ this .$refs .scroller .scrollToBottom ()
120
+ },
121
+
122
+ startStream () {
123
+ if (this .streaming ) return
124
+ this .streaming = true
125
+ this .addMessage ()
126
+ },
127
+
128
+ stopStream () {
129
+ this .streaming = false
130
+ },
131
+ },
132
+ }
133
+ </script >
134
+
135
+ <style scoped>
136
+ .chat-demo ,
137
+ .scroller {
138
+ height : 100% ;
139
+ }
140
+
141
+ .chat-demo {
142
+ overflow : hidden ;
143
+ }
144
+
145
+ .notice {
146
+ padding : 24px ;
147
+ font-size : 20px ;
148
+ color : #999 ;
149
+ }
150
+
151
+ .message {
152
+ display : flex ;
153
+ min-height : 32px ;
154
+ padding : 12px ;
155
+ box-sizing : border-box ;
156
+ }
157
+
158
+ .avatar {
159
+ flex : auto 0 0 ;
160
+ width : 32px ;
161
+ height : 32px ;
162
+ border-radius : 50% ;
163
+ margin-right : 12px ;
164
+ }
165
+
166
+ .avatar .image {
167
+ max-width : 100% ;
168
+ max-height : 100% ;
169
+ border-radius : 50% ;
170
+ }
171
+
172
+ .index ,
173
+ .text {
174
+ flex : 1 ;
175
+ }
176
+
177
+ .text {
178
+ max-width : 400px ;
179
+ }
180
+
181
+ .index {
182
+ opacity : .5 ;
183
+ }
184
+
185
+ .index span {
186
+ display : inline-block ;
187
+ width : 160px ;
188
+ text-align : right ;
189
+ }
190
+ </style >
Original file line number Diff line number Diff line change @@ -7,6 +7,7 @@ import Dynamic from './components/DynamicScrollerDemo.vue'
7
7
import TestChat from './components/TestChat.vue'
8
8
import SimpleList from './components/SimpleList.vue'
9
9
import HorizontalDemo from './components/HorizontalDemo.vue'
10
+ import ChatDemo from './components/ChatDemo.vue'
10
11
11
12
Vue . use ( VueRouter )
12
13
@@ -18,5 +19,6 @@ export default new VueRouter({
18
19
{ path : '/test-chat' , name : 'test-chat' , component : TestChat } ,
19
20
{ path : '/simple-list' , name : 'simple-list' , component : SimpleList } ,
20
21
{ path : '/horizontal' , name : 'horizontal' , component : HorizontalDemo } ,
22
+ { path : '/chat' , name : 'chat' , component : ChatDemo } ,
21
23
] ,
22
24
} )
You can’t perform that action at this time.
0 commit comments