分片加载
let totalElement = 100000 ;
let index = 0 ;
const load = ( size = 50 ) => {
index++ ;
let content;
requestAnimationFrame ( ( ) => {
for ( let i = 0 ; i <= index * size; i++ ) {
const element = document. createElement ( "div" ) ;
element. innerHTML = i + ( index - 1 ) * size;
document. body. appendChild ( element) ;
}
load ( ) ;
} , 0 ) ;
if ( index >= totalElement) return ;
} ;
load ( ) ;
虚拟滚动
< template>
< div class = "scroll-container" ref= "scrollContainer" >
< div class = "scroll-viewport" : style= "{transform: `translateY(${offset}px)`}" >
< div class = "scroll-item" v- for = "item in visibleData" : key= "item[keyValue] || item.index" >
< slot : item= "item" > < / slot>
< / div>
< / div>
< div class = "scroll-bar" ref= "scrollBar" : style= "{height: scrollBarHeight}" > < / div>
< / div>
< / template>
< script>
export default {
name : 'VirtualList' ,
props : {
keyValue : {
type : String,
default : ''
} ,
items : {
type : Array,
default : ( ) => [ ]
} ,
size : {
type : Number,
require : true ,
default : 0
} ,
remain : {
type : Number,
require : true ,
default : 0
} ,
reserve : {
type : Object,
default : null
}
} ,
data ( ) {
return {
start : 0 ,
end : this . remain,
offset : 0
} ;
} ,
computed : {
preCount ( ) {
if ( ! this . reserve) {
return Math. min ( this . start, this . remain) ;
}
return Math. min ( this . start, this . reserve. remain) ;
} ,
nextCount ( ) {
if ( ! this . reserve) {
return Math. min ( this . items. length - this . end, this . remain) ;
}
return Math. min ( this . items. length - this . end, this . reserve. end) ;
} ,
formatData ( ) {
return this . items. map ( ( item, index ) => ( { ... item, index} ) ) ;
} ,
visibleData ( ) {
return this . formatData. slice ( this . start - this . preCount, this . end + this . nextCount) ;
} ,
scrollBarHeight ( ) {
return this . size * this . items. length + 'px' ;
}
} ,
mounted ( ) {
this . init ( ) ;
this . $once ( 'hook:beforeDestroy' , ( ) => {
this . $refs. scrollContainer. removeEventListener ( 'scroll' ) ;
} ) ;
} ,
methods : {
init ( ) {
this . $refs. scrollContainer. addEventListener ( 'scroll' , this . scrollDebounce ( ) ) ;
} ,
handleScroll ( e ) {
this . scrollDebounce ( e) ;
} ,
scrollDebounce ( ) {
return this . debounce ( ( e ) => {
console. log ( 'scroll' ) ;
const scrollTop = e. target. scrollTop;
this . start = Math. floor ( scrollTop / this . size) ;
this . end = this . start + this . remain;
this . offset = scrollTop - this . size * this . preCount - scrollTop % this . size;
} ) ;
} ,
debounce ( cb, wait = 10 ) {
let timer = null ;
return ( e ) => {
if ( timer) {
clearTimeout ( timer) ;
timer = null ;
}
timer = setTimeout ( ( ) => {
cb ( e) ;
clearTimeout ( timer) ;
timer = null ;
} , wait) ;
} ;
}
}
} ;
< / script>
< style scoped lang= "less" >
. scroll- container{
overflow- y: auto;
position : relative;
height : 100 % ;
. scroll- viewport{
position : absolute;
top : 0 ;
width : 100 % ;
}
}
< / style>