Authored by yyq

fix click

<template>
<div ref="scroll" class="aaa">
<div ref="listBlock"
:scroll-events="['scroll', 'scroll-end', 'before-scroll-start']"
@scroll="onScrollHandle"
@scroll-end="onScrollEndHandle"
@before-scroll-start="beforeScrollStartHandle"
v-bind="$attrs" v-on="$listeners">
<div class="infinite-list-block" :class="{'list-scroll': scrolling}">
<div class="infinite-list-chunk"
v-for="(chunk, chunkIndex) in visibleList"
:key="chunkIndex"
:data-chunk-id="chunkIndex"
:style="`${chunk.hide ? 'height:' + chunk.height + 'px' : ''}`">
<template v-if="!chunk.hide">
<div class="infinite-list-item"
v-for="(item, index) in chunk.chunkList"
:key="`${chunkIndex}-${index}`">
<slot name="item" :data="item"></slot>
</div>
</template>
</div>
</div>
<div class="list-footer">
<Loading v-show="!noMore" class="load-icon" :size="20"></Loading>
<p v-show="noMore" class="list-nomore">
没有更多了
</p>
</div>
</div>
</div>
</template>
<script>
import {Scroll, Loading} from 'cube-ui';
import {chunk, takeRight, forEach} from 'lodash';
export default {
name: 'InfiniteList',
data() {
return {
scrolling: false,
list: [],
visibleList: [],
chunkSize: 10,
currentIndex: 0,
startOffset: 0,
noMore: false
};
},
props: {
offset: {
type: Number,
default: 100
},
onFetch: {
type: Function,
required: true
},
thumbs: {
type: Array,
default() {
return [];
}
}
},
watch: {
list(newV, oldV) {
let index = oldV.length;
if (newV.length <= index) {
index = 0;
}
this.updateList(index);
}
},
mounted() {
this.scrollHeight = this.$el.offsetHeight;
this.$refs.scroll.onscroll = () => {
console.log(this.$refs.scroll.scrollTop);
console.log(this.$refs.listBlock.scrollTop);
};
this.getData();
this.updateList();
},
methods: {
updateList(index) {
let list = this.visibleList;
if (!Number(index)) {
index = 0;
list = [];
}
let chunks = [];
if (this.list.length) {
chunk(takeRight(this.list, this.list.length - index), this.chunkSize).forEach(val => {
chunks.push({
chunkList: val
});
});
}
this.visibleList = list.concat(chunks);
setTimeout(() => {
// this.$refs.scroll.refresh();
}, 100);
},
getData() {
this.onFetch().then((res) => {
if (!res) {
this.noMore = true;
} else {
this.list = this.list.concat(res);
}
});
},
onScrollHandle() {
},
onScrollEndHandle(scroll) {
if (1000 - scroll.y > this.$refs.listBlock.offsetHeight) {
this._timer && clearTimeout(this._timer);
this._timer = setTimeout(() => {
this.getData();
}, 50);
}
this.clacViewChunks(-scroll.y)
this.scrolling = false;
},
beforeScrollStartHandle() {
this.scrolling = true;
},
clacViewChunks(top) {
if (this.list.length < 50) {
return;
}
//
let time = new Date();
let $children = this.$refs.listBlock.children;
let height = 0;
let hasChange = false;
forEach($children, (dom, index) => {
let chunk = this.visibleList[index];
let hide = false;
let h = dom.offsetHeight;
if (height > top + this.scrollHeight * 5 || height + h < top - this.scrollHeight * 4) {
hide = true;
}
if (!!chunk.hide !== hide) {
hasChange = true;
chunk.hide = hide;
chunk.height = h;
}
height += h;
});
if (hasChange) {
time = new Date();
this.visibleList = [...this.visibleList];
// this.$nextTick(() => {
// alert(new Date() - time);
// });
}
console.log(hasChange);
}
},
components: {
Scroll,
Loading
}
};
</script>
<style lang="scss">
.aaa {
height: 100%;
overflow: scroll;
}
.list-scroll {
position: relative;
&:after {
content: '';
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1;
}
}
.list-footer {
text-align: center;
padding: 20px;
> * {
display: inline-block;
}
}
</style>