無限滾動
很多人以為無限滾動,就是只是觸底加載,但是加載到一定長度,頁面會爆炸!!
真正的無限加載是真正的無限!
頁面僅渲染可見的元素,對不可見的不占用頁面節點,才可實現真正的無限滾動。
對 IntersectionObserver 監聽元素可見的思考
可以實現:
1. 觸頂:移除下面,渲染上面,解除頂部占位
2. 觸底:移除上面,渲染下面,增加頂部占位
實現的技巧:
1. 只修改一個變量達到效果。
2. 用計算屬性動態得出該渲染什么。
3. `threshold`使用`0.0000001`,判斷`intersectionRatio > 0.01`比較穩(能保證真正的可見)。
4. end元素,向上相對定位,實現預加載(提前觸底)。
實現代碼:
視圖層
<template>
<div class="infinity-sroll-container">
<div :style="{ paddingTop: (showStart - 1) * 200 + 'px' }">
<div data-site="start" ref="start"></div>
<div
class="item"
v-for="(n, i) in showList"
:key="i"
:style="{backgroundColor: colors[n % 10]}"
>
{{n}}
</div>
<div class="end" data-site="end" ref="end"></div>
</div>
</div>
</template>
邏輯層
export default {
data() {
return {
showStart: 1,
colors: [
'#CCCC33',
'#CCCCCC',
'#FFFFCC',
'#0099FF',
'#33CC99',
'#FFFFFF',
'#ff9900',
'#99CC33',
'#99CCFF',
'#CC9999'
]
};
},
computed: {
showList() {
const result = [];
for (let i = 0; i < 20; i += 1) {
result.push(this.showStart + i);
}
return result;
}
},
mounted() {
const io = new IntersectionObserver((entries) => {
if (entries[0].intersectionRatio > 0.001) {
if (entries[0].target.dataset.site === 'end') {
this.showStart += 10;
} else {
this.showStart = (this.showStart - 10 <= 1) ? 1 : (this.showStart - 10);
}
}
}, {
threshold: [0.000001],
});
io.observe(this.$refs.start);
io.observe(this.$refs.end);
}
};
樣式層
// lang="scss" scoped
.infinity-sroll-container{
.item {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 200px;
font-weight: bold;
}
.end {
position: relative;
top: -400px;
}
}