11import Vue from 'vue' ;
22import { throttle } from './util' ;
33
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-
334Vue . component ( 'virtual-list' , {
345
356 props : {
@@ -41,18 +12,36 @@ Vue.component('virtual-list', {
4112 type : Number ,
4213 required : true
4314 } ,
44- pageCounts : {
15+ amount : {
4516 type : Number ,
4617 required : true
4718 }
4819 } ,
4920
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+
5038 methods : {
5139 onScroll : throttle ( function ( ) {
40+ let delta = this . $options . delta ;
5241 let scrollTop = this . $refs . container . scrollTop ;
5342 let listHeight = this . $refs . listbox . offsetHeight ;
5443
55- saveDirect ( scrollTop ) ;
44+ this . saveDirect ( scrollTop ) ;
5645
5746 // scroll to top
5847 if ( scrollTop === 0 ) {
@@ -70,19 +59,38 @@ Vue.component('virtual-list', {
7059 }
7160 } , 16 , true , true ) ,
7261
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+
7373 showNext ( ) {
74+ let delta = this . $options . delta ;
75+
7476 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+ }
7683 } ,
7784
7885 showPrev ( ) {
79- delta . page_type = 'PREV' ;
86+ this . $options . delta . page_type = 'PREV' ;
8087 this . $forceUpdate ( ) ;
8188 this . $emit ( 'prev' ) ;
8289 } ,
8390
8491 filter ( items ) {
8592 let length = items . length ;
93+ let delta = this . $options . delta ;
8694 let nowStartIndex , udf , list = [ ] ;
8795
8896 if ( ! delta . total ) {
@@ -92,14 +100,14 @@ Vue.component('virtual-list', {
92100 if ( delta . page_type === 'PREV' ) {
93101 // already the first page
94102 if ( delta . start_index === 0 ) {
95- list = items . slice ( 0 , this . pageCounts ) ;
103+ list = items . slice ( 0 , this . amount ) ;
96104 } else {
97105 list = items . filter ( ( item , index ) => {
98- if ( index === delta . start_index - this . pageCounts ) {
106+ if ( index === delta . start_index - this . amount ) {
99107 nowStartIndex = index ;
100108 }
101109
102- return index >= ( delta . start_index - this . pageCounts )
110+ return index >= ( delta . start_index - this . amount )
103111 && index < delta . start_index ;
104112 } ) ;
105113
@@ -110,54 +118,65 @@ Vue.component('virtual-list', {
110118 delta . padding_top = delta . start_index * this . unit ;
111119 }
112120 } else {
121+ // flipping next or first render
122+
113123 // virtual list has no any increase
124+ // just flip to next page from start index
114125 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+ } ) ;
116130 } else {
117131 list = items . filter ( ( item , index ) => {
118- if ( index === delta . start_index + this . pageCounts ) {
132+ if ( index === delta . start_index + this . amount ) {
119133 nowStartIndex = index ;
120134 }
121135
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 ) ;
124138 } ) ;
125139
126140 if ( nowStartIndex !== udf ) {
127141 delta . start_index = nowStartIndex ;
128142 }
129143
130- // item counts of all virtual list
144+ // save virtual list new length
131145 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
133148 delta . all_padding = ( length - this . remain ) * this . unit ;
134- // padding-top piexl
135- delta . padding_top = delta . start_index * this . unit ;
136149 }
150+
151+ // padding-top piexl
152+ delta . padding_top = delta . start_index * this . unit ;
137153 }
138154
139155 return list ;
140156 }
141157 } ,
142158
143159 beforeMount ( ) {
144- delta . view_height = this . remain * this . unit ;
160+ this . $options . delta . view_height = this . remain * this . unit ;
145161 } ,
146162
147163 mounted ( ) {
164+ let delta = this . $options . delta ;
148165 delta . joints = Math . ceil ( this . remain / 2 ) ;
149166 delta . bench_padding = delta . joints * this . unit ;
150167 } ,
151168
152169 beforeUpdate ( ) { } ,
153170
154171 updated ( ) {
172+ let delta = this . $options . delta ;
155173 window . requestAnimationFrame ( ( ) => {
156174 this . $refs . container . scrollTop = delta . padding_top + delta . bench_padding ;
157175 } ) ;
158176 } ,
159177
160178 render ( createElement ) {
179+ let delta = this . $options . delta ;
161180 let slots = this . $slots . default ;
162181 let showList = this . filter ( slots ) ;
163182
0 commit comments