昨天部门会议,领导提出一个需求,就是当一个前端页面有上百个图表或者其它元素,对应的接口有许多时,为了体验效果,不能一次性加载全部的数据,只有当元素滚动到可视区域内时,再进行相应接口的调用,也就是数据的懒加载。
如下图所示:目前出现在可视区域内部的只有图表0 图表1 图表2 图表3
4个元素,控制台也能拿到对应的索引或者dom
元素。
当滚动页面出现图表4 图表5
出现在可视区域时,控制台也能拿到对应的索引或者dom
元素
而且页面回滚的时候,不会再次请求接口。
能拿到当前可视区域展示的dom
元素,就可以获取对应的接口数据了。
下面介绍实现方法:
1.在main.js
中添加自定义指令
Vue.directive('lazy', {
bind: function (el, binding) {
let lazyLoadObser = new IntersectionObserver((entries, observer) => {
entries.forEach((entry, index) => {
let lazyImage = entry.target
if (entry.intersectionRatio > 0) {
binding.value.throttle(binding.value.getData,200)(binding.value.id, lazyLoadObser, lazyImage)
}
})
})
lazyLoadObser.observe(el)
}
})
2.页面上使用指令——以图片懒加载为例
html
部分:
<div class="kjWrap">
<div class="kj" v-for="(item, index) in originData" :key="index">
<img v-lazy="{ getData: getData, id: item.id, throttle: throttle }" :src="item.img"/>
</div>
</div>
样式部分:
<style lang="less" scoped>
.kjWrap {
display: flex;
flex-wrap: wrap;
.kj {
width: 50%;
height: 200px;
border: 1px solid red;
img {
width: 100%;
height: 100%;
object-fit:cover;
}
}
}
</style>
script
部分:
data(){
return{
originData: [
{
id: 0},
{
id: 1},
{
id: 2},
{
id: 3},
{
id: 4},
{
id: 5},
{
id: 6},
{
id: 7},
{
id: 8},
{
id: 9},
],
}
}
methods:{
// 闭包节流
throttle(fn, wait) {
let timer = '';
return function(...args) {
if (timer) return;
timer = setTimeout(() => {
timer = null;
fn.apply(this, args);
}, wait);
};
},
getData(id, lazyLoadObser, lazyImage) {
console.log('开始加载数据了', id, lazyLoadObser, lazyImage);
// 解绑监听事件
lazyLoadObser.unobserve(lazyImage);
let list = [
'https://img2.baidu.com/it/u=2632350353,4292959661&fm=253&fmt=auto&app=138&f=JPEG?w=819&h=500',
'https://img2.baidu.com/it/u=2632350353,4292959661&fm=253&fmt=auto&app=138&f=JPEG?w=819&h=500',
'https://img1.baidu.com/it/u=147161764,3142008484&fm=253&fmt=auto&app=120&f=JPEG?w=654&h=368',
'https://img1.baidu.com/it/u=147161764,3142008484&fm=253&fmt=auto&app=120&f=JPEG?w=654&h=368',
'https://img1.baidu.com/it/u=147161764,3142008484&fm=253&fmt=auto&app=120&f=JPEG?w=654&h=368',
'https://img1.baidu.com/it/u=147161764,3142008484&fm=253&fmt=auto&app=120&f=JPEG?w=654&h=368',
'https://img0.baidu.com/it/u=3419722502,755567528&fm=253&fmt=auto&app=138&f=JPEG?w=1000&h=500',
'https://img0.baidu.com/it/u=3419722502,755567528&fm=253&fmt=auto&app=138&f=JPEG?w=1000&h=500',
'https://img0.baidu.com/it/u=3419722502,755567528&fm=253&fmt=auto&app=138&f=JPEG?w=1000&h=500',
'https://img0.baidu.com/it/u=3419722502,755567528&fm=253&fmt=auto&app=138&f=JPEG?w=1000&h=500',
'https://img0.baidu.com/it/u=3419722502,755567528&fm=253&fmt=auto&app=138&f=JPEG?w=1000&h=500',
];
this.$set(this.originData[id], 'img', list[id]);
},
}
完成!!!
如果不是图片,而是其它元素,也可以通过此方法实现,只需要将html
中的img
部分更换掉,script
中的getData
方法中添加对应的接口调用即可。
多多积累,多多收获!!!