1
1
import Vue from 'vue' ;
2
2
import { throttle } from './util' ;
3
3
4
- // some data help to calculate
5
- let delta = {
6
- // about scroll
7
- direct : '' ,
8
- last_top : 0 ,
9
- page_type : '' ,
10
-
11
- // about data
12
- total : 0 ,
13
- joints : 0 ,
14
- start_index : 0 ,
15
-
16
- // about style
17
- view_height : 0 ,
18
- all_padding : 0 ,
19
- padding_top : 0 ,
20
- bench_padding : 0
21
- } ;
22
-
23
- // save scroll direct and last scroll position
24
- const saveDirect = ( scrollTop ) => {
25
- if ( ! delta . last_top ) {
26
- delta . last_top = scrollTop ;
27
- } else {
28
- delta . direct = delta . last_top > scrollTop ? 'UP' : 'DOWN' ;
29
- delta . last_top = scrollTop ;
30
- }
31
- } ;
32
-
33
4
Vue . component ( 'virtual-list' , {
34
5
35
6
props : {
@@ -41,18 +12,36 @@ Vue.component('virtual-list', {
41
12
type : Number ,
42
13
required : true
43
14
} ,
44
- pageCounts : {
15
+ amount : {
45
16
type : Number ,
46
17
required : true
47
18
}
48
19
} ,
49
20
21
+ // an object helping to calculate
22
+ delta : {
23
+ // scroll
24
+ direct : '' ,
25
+ last_top : 0 ,
26
+ page_type : '' ,
27
+ // data
28
+ total : 0 ,
29
+ joints : 0 ,
30
+ start_index : 0 ,
31
+ // style
32
+ view_height : 0 ,
33
+ all_padding : 0 ,
34
+ padding_top : 0 ,
35
+ bench_padding : 0
36
+ } ,
37
+
50
38
methods : {
51
39
onScroll : throttle ( function ( ) {
40
+ let delta = this . $options . delta ;
52
41
let scrollTop = this . $refs . container . scrollTop ;
53
42
let listHeight = this . $refs . listbox . offsetHeight ;
54
43
55
- saveDirect ( scrollTop ) ;
44
+ this . saveDirect ( scrollTop ) ;
56
45
57
46
// scroll to top
58
47
if ( scrollTop === 0 ) {
@@ -70,19 +59,38 @@ Vue.component('virtual-list', {
70
59
}
71
60
} , 16 , true , true ) ,
72
61
62
+ saveDirect ( scrollTop ) {
63
+ let delta = this . $options . delta ;
64
+
65
+ if ( ! delta . last_top ) {
66
+ delta . last_top = scrollTop ;
67
+ } else {
68
+ delta . direct = delta . last_top > scrollTop ? 'UP' : 'DOWN' ;
69
+ delta . last_top = scrollTop ;
70
+ }
71
+ } ,
72
+
73
73
showNext ( ) {
74
+ let delta = this . $options . delta ;
75
+
74
76
delta . page_type = 'NEXT' ;
75
- this . $emit ( 'bottom' ) ;
77
+ if ( delta . total - delta . start_index <= this . amount ) {
78
+ this . $emit ( 'bottom' ) ;
79
+ } else {
80
+ delta . start_index = delta . start_index + this . amount ;
81
+ this . $forceUpdate ( ) ;
82
+ }
76
83
} ,
77
84
78
85
showPrev ( ) {
79
- delta . page_type = 'PREV' ;
86
+ this . $options . delta . page_type = 'PREV' ;
80
87
this . $forceUpdate ( ) ;
81
88
this . $emit ( 'prev' ) ;
82
89
} ,
83
90
84
91
filter ( items ) {
85
92
let length = items . length ;
93
+ let delta = this . $options . delta ;
86
94
let nowStartIndex , udf , list = [ ] ;
87
95
88
96
if ( ! delta . total ) {
@@ -92,14 +100,14 @@ Vue.component('virtual-list', {
92
100
if ( delta . page_type === 'PREV' ) {
93
101
// already the first page
94
102
if ( delta . start_index === 0 ) {
95
- list = items . slice ( 0 , this . pageCounts ) ;
103
+ list = items . slice ( 0 , this . amount ) ;
96
104
} else {
97
105
list = items . filter ( ( item , index ) => {
98
- if ( index === delta . start_index - this . pageCounts ) {
106
+ if ( index === delta . start_index - this . amount ) {
99
107
nowStartIndex = index ;
100
108
}
101
109
102
- return index >= ( delta . start_index - this . pageCounts )
110
+ return index >= ( delta . start_index - this . amount )
103
111
&& index < delta . start_index ;
104
112
} ) ;
105
113
@@ -110,54 +118,65 @@ Vue.component('virtual-list', {
110
118
delta . padding_top = delta . start_index * this . unit ;
111
119
}
112
120
} else {
121
+ // flipping next or first render
122
+
113
123
// virtual list has no any increase
124
+ // just flip to next page from start index
114
125
if ( length === delta . total ) {
115
- list = items ;
126
+ list = items . filter ( ( item , index ) => {
127
+ return index >= delta . start_index
128
+ && index < delta . start_index + this . amount ;
129
+ } ) ;
116
130
} else {
117
131
list = items . filter ( ( item , index ) => {
118
- if ( index === delta . start_index + this . pageCounts ) {
132
+ if ( index === delta . start_index + this . amount ) {
119
133
nowStartIndex = index ;
120
134
}
121
135
122
- return index >= ( delta . start_index + this . pageCounts )
123
- && index < ( delta . start_index + this . pageCounts * 2 ) ;
136
+ return index >= ( delta . start_index + this . amount )
137
+ && index < ( delta . start_index + this . amount * 2 ) ;
124
138
} ) ;
125
139
126
140
if ( nowStartIndex !== udf ) {
127
141
delta . start_index = nowStartIndex ;
128
142
}
129
143
130
- // item counts of all virtual list
144
+ // save virtual list new length
131
145
delta . total = length ;
132
- // all padding pixel, except remain in viewport items
146
+ // all padding pixel, include top and bottom
147
+ // except remain and calculate when component update
133
148
delta . all_padding = ( length - this . remain ) * this . unit ;
134
- // padding-top piexl
135
- delta . padding_top = delta . start_index * this . unit ;
136
149
}
150
+
151
+ // padding-top piexl
152
+ delta . padding_top = delta . start_index * this . unit ;
137
153
}
138
154
139
155
return list ;
140
156
}
141
157
} ,
142
158
143
159
beforeMount ( ) {
144
- delta . view_height = this . remain * this . unit ;
160
+ this . $options . delta . view_height = this . remain * this . unit ;
145
161
} ,
146
162
147
163
mounted ( ) {
164
+ let delta = this . $options . delta ;
148
165
delta . joints = Math . ceil ( this . remain / 2 ) ;
149
166
delta . bench_padding = delta . joints * this . unit ;
150
167
} ,
151
168
152
169
beforeUpdate ( ) { } ,
153
170
154
171
updated ( ) {
172
+ let delta = this . $options . delta ;
155
173
window . requestAnimationFrame ( ( ) => {
156
174
this . $refs . container . scrollTop = delta . padding_top + delta . bench_padding ;
157
175
} ) ;
158
176
} ,
159
177
160
178
render ( createElement ) {
179
+ let delta = this . $options . delta ;
161
180
let slots = this . $slots . default ;
162
181
let showList = this . filter ( slots ) ;
163
182
0 commit comments