懒加载 前端优化:懒加载思考

偷偷观察

默默关注

懒加载 前端优化:懒加载思考


文章图片

约翰·杨(John young)于2018年加入去哪儿,很荣幸能与许多优秀的同事一起努力工作。目前在大住宿/大前端/综合业务团队,主要负责专题系统的开发和优化,涉及前端组件的开发和后端节点项目的开发。希望在大前端架构上有所突破,帮助同事和团队提高大前端领域的开发效率。
一.导言
在优化系统时,如果仅限于前端类别,可以使用的方法非常有限。我们平时能想到的就是如何让第一屏更流畅,提高用户体验。惰性加载是指合理延迟图片和静态资源的加载,甚至延迟接口或业务逻辑的执行,以达到首屏空的最大性能,达到页面首屏更快的渲染效果。这个思路适合很多前端项目的优化场景。
二、实现思路1、资源站、
延迟加载时,通常需要跳过最初的执行步骤。比如懒人加载图片时,需要立标签,提前设置图片的宽度和高度,使用data-*属性设置要请求图片的地址。此时图片还没有被浏览器下载。
<img class="qLazy" data-original='https://xyz.abc.com/common/logo.png' />因为此时没有设置src属性,所以不会加载数据原始地址对应的图片。如果图片地址直接在src属性中设置,浏览器解析后会直接下载,这样就失去了懒加载的意义。
2.监控滚动事件
惰性加载时,需要制作惰性加载的容器。例如,一些可滚动的内容列表区域。然而,在实际开发中,容器通常没有明确地公式化。比如手机经常有一个很长的列表,随着整个页面一起滚动。此时,如果执行惰性加载优化,默认滚动容器应该是窗口对象。
3.确定资源位置是否在窗口中
这个函数是延迟加载的核心,因为延迟加载也可以叫做延迟加载,但是什么时候加载呢?当用户看到或将要看到要加载的资源时,他必须提前加载资源。这样,当用户看到资源时,资源已经被加载,可以给用户更好的体验。用网上的一张图片来说明:

懒加载 前端优化:懒加载思考


文章图片

也就是说,当要加载的绿色页面元素即将进入蓝色可视区域或已经进入可视区域时,执行惰性加载方法。
4.判断是加载资源还是执行相应的回调逻辑
该功能可以根据业务进行扩展或更改。懒加载的初衷只是设计在图片标签上,因为大部分手机页面会有80%左右是图片,合理控制图片的加载可以更好的提升用户体验。然而,也有例外。随着前端的功能越来越强大,很多渲染任务会交给前端,很多业务逻辑会被前端控制。因此,系统希望扩展一些惰性执行功能,以确保首先完成第一个屏幕逻辑,然后延迟后续渲染或复杂操作。下面是一些懒加载实现的源代码。
function QLazyLoader(setting) {var _setting = {selector: '.qLazy',// 事件名event: 'scroll',// 默认绑定 evnet 的对象容器container: setting.container || window,// 获取 src 的 data 属性,默认 data-attrbuteattribute: 'data-original',// 设置懒加载类型 默认为img 选项: 图片:img 只执行回调:callloadtype: 'img',// 回调事件,元素出现在视口中 functionappear: null,// 触发 load 事件时执行的回调 functionload: null};//省略:进行滚动监听//省略:判断是否出现再视窗内//如果元素出现在视窗内elements.each(function () {var dom = this;var jqThis = $(dom);var qSrc = https://www.qqbk.com/html/jqThis.attr(setting.attribute);var loadAction = function() {};var loadedCall = function() {elements = $(grepElements(elements));if (setting.load) {setting.load.call(dom, jqThis, elements.length, setting);}}if (/img|background-image/.test(setting.loadtype) && qSrc) {var _img = jqThis;// 开始懒加载图片if (!_img.attr('src')) {jqThis.attr('src', qSrc);}_img.one('error', function () {console.log('qSrc loaded error', qSrc);});}if (/js/.test(setting.loadtype) && qSrc) {loadAction = function() {Load(qSrc, loadedCall);}}if (/css/.test(setting.loadtype) && qSrc) {loadAction = function() {LoadStyle(qSrc, loadedCall);}}if (/call/.test(setting.loadtype)) {loadAction = loadedCall;}jqThis.one(APPEAR_EVENT, function (e) {if (!dom.loaded) {if (setting.appear) {setting.appear.call(dom, $(this), elements.length, setting);}loadAction();}});});} 三、如何判断资源位置是否出现在视窗内 1、根据可视区域高度和滚动高度以及元素距离页面顶端的距离进行计算 function isElementInViewport (el) {// 获取div距离顶部的偏移量var offsetTop = el.offsetTop;// 获取屏幕高度var clientHeight = document.documentElement.clientHeight;// 屏幕卷去的高度var scrollTop = document.documentElement.scrollTop;if( clientHeight + scrollTop > offsetTop ) {console.log("已经进入可视区");} else {console.log("并没有进入可视区");}}注意:document.documentElement的兼容性超出了本讲的范围。

推荐阅读