目录
一、vue-observe-visibility简介
vue-observe-visibility是vue的懒加载插件,他可以实现元素出现在视口可见范围之内,调用回调函数,执行一系列操作,还可以控制是否监听元素,是否只监听一次以及节流监听等,具体api以及安装方法,可以参照官方文档:安装 | vue-observe-visibility
二、问题描述
实现元素出现在可视范围内,依次向后台请求数据,数据回来之后依次加载图表。
如果单纯使用vue-observe-visibility插件,那么如果滚轮滑动的较快,可能一次性会有很多元素出现在可视范围内,这时会造成同时向后台发送请求的情况,如果服务器配置不高,可能会导致服务器崩溃(对,没错,我们公司的服务器就摇摇欲坠,经不起考验),那如何解同时发起请求的问题呢?
三、逻辑步骤
- 创建observeVisibily.js文件,定义ObserveVisible类
- 定义数组queueList,用于存放方法队列
- 队列方法是否执行标识queunIsRun,防止滚轮滑动过快,短时间内大量调用执行队列方法
- 定义所监听元素对象isVisi,用于确定哪个对象出现在了可视范围内
- 初始化元素对象方法createIsvisi,用于创建所需对象格式
// 获取初始element列表,用于标识元素是否可见,els参数为数组形式,传入元素唯一标识 // [ 'el1', 'el2' ] createIsvisi(els) { els.forEach(item => { Vue.set(this.isVisi, item, { loading: false, observe: true }) }) }
-
向任务队列添加方法函数addQueue
// 添加任务队列 addQueue({ visi, func, params }) { this.queueList.push({ visi, func, params, }) }
-
执行任务队列函数doQueue,调用doQueue时,需先判断queunIsRun是否为true,如果为true,则证明正在执行任务队列,这时直接return。如果为false,则判断任务队列数组长度,如果不为0,那么弹出数组第一列,执行弹出的方法,结束之后递归调用自身,直至任务队列长度为0(注意,这里递归调用自身需要传入标识isSelf,用于与queunIsRun联合判断,当isSelf为true时,无论queunIsRun是什么状态,都需要执行自身 )
// 执行任务队列 async doQueue(isSelf) { if (!isSelf && this.queunIsRun) return this.queunIsRun = true; try { if (this.queueList.length) { const item = this.queueList.shift(); await item.func(item.params); Vue.set(this.isVisi[item.visi], 'loading', false) await this.doQueue(true); } else { this.closeQueue() } } catch (err) { console.log(err); if (this.queueList.length) { this.doQueue(true); } else { this.clearQueue(); } } }
-
关闭任务队列函数closeQueue
// 关闭任务队列 closeQueue() { this.queunIsRun = false; this.isSearchDisable = false; }
-
清空任务队列clearQueue,用于调用函数出错时,重置状态
// 清空任务队列,关闭所有loading状态 clearQueue() { this.closeQueue() this.queueList = [] Object.keys(this.isVisi).forEach( item => Vue.set(this.isVisi[item], 'loading', false) ); }
-
重置元素列表状态方法resetIsvisi
// 重置element列表状态 resetIsvisi() { Object.keys(this.isVisi).forEach( item => Vue.set(this.isVisi[item], 'observe', true) ); }
-
元素进入可视范围内函数visiElement
// 元素进入可见范围
visiElement(el) {
this.isSearchDisable = true;
Vue.set(this.isVisi[el], 'loading', true)
Vue.set(this.isVisi[el], 'observe', false)
}
四、使用方法
- 在所需文件中引入observeVisibily.js
import { ObserveVisible } from "../utils/observeVisibily.js";
- 定义实例参数observeVisible
// 需要懒加载的元素 observeVisible: null, // 需要懒加载的元素 isVisiList: [ "el1", "el2", "el3" ],
-
在created方法中创建实例对象
this.observeVisible = new ObserveVisible(this.isVisiList);
-
定义懒加载回调函数visibilityChanged
visibilityChanged(element) { return async (isVisible) => { if (isVisible) { try { this.observeVisible.visiElement(element); switch (element) { case "el1": this.observeVisible.addQueue({ func: this.el1Func, visi: "el1", params: this.params, }); break; case "el2": this.observeVisible.addQueue({ func: this.el2Func, visi: "el2", params: this.params, }); break; case "el3": this.observeVisible.addQueue({ func: this.el3Func, visi: "el3", params: this.params, }); break; default: break; } this.observeVisible.doQueue(); } catch (err) { console.log("懒加载错误 =", err); } } }; }
-
在所需元素上绑定方法,其中有用到 vue-observe-visibility 相关api,具体请查看官网
<div v-loading="observeVisible.isVisi.el1.loading" v-observe-visibility=" observeVisible.isVisi.el1.observe ? { callback: visibilityChanged('el1'), once: true } : false"> </div>
四、结语
在工作中,经常能遇到各种需求,你觉得不合理的需求,可能为了适应当前环境而产生的, 不能改变需求,那么只能改变自己。如果有小伙伴需要完整代码,可以私信我,看到了会回,欢迎点赞收藏~