资讯专栏INFORMATION COLUMN

函数节流和图片懒加载

tomlingtm / 902人阅读

摘要:然而,如果前一个定时器尚未执行,其实就是替换为一个新的定时器,目的是只有在执行函数的请求停止了一段时间后才执行。首先清除之前设置的任何定时器,定时器是储存在函数的属性中的。

导读

这篇文章中主要介绍一下函数节流,然后给了一个图片懒加载的例子,说图片懒加载的时候顺带提了下怎么使用JS获取页面的宽高,卷上去的长度等。参考来源主要是《JavaScript高级程序设计》。

函数节流

浏览器的DOM操作比起非DOM交互需要更多的内存和cpu时间,连续过多的DOM操作可能会导致浏览器挂起甚至崩溃。比如使用onresize,onscroll这些可能会被连续触发的事件的时候,如果事件处理程序中进行了过多地DOM操作,可能就会使得浏览器崩溃。而为了绕开这个问题,可能就需要使用到函数节流。
比如:

function resizeDiv(){          //在窗口尺寸改变的时候,调整div的高度
    var div = document.getElementById("myDiv");
    console.log(div.offsetWidth);
    div.style.height = div.offsetWidth + "px";

}
window.onresize = function(){
    resizeDiv();
}

上面的代码在我简单的拉伸窗口的时候被连续执行了,如果是更复杂的DOM操作,很可能使得浏览器崩溃。其实我想要的只是在我改变完窗口大小后,再调整一次myDiv的高度。

函数节流的指导思想是:某些代码可以在没有间断的情况下重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔后执行代码。当第二次调用该函数的时候,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作没有意义。然而,如果前一个定时器尚未执行,其实就是替换为一个新的定时器,目的是只有在执行函数的请求停止了一段时间后才执行。

上代码:

function throttle(method,context){
    clearTimeout(method.tId);            //{1}
    method.tId = setTimeout(function(){
        method.call(context);            //{2}
    },100);
}

throttle方法接收两个参数:要执行的函数及在哪个作用域中执行。{1}首先清除之前设置的任何定时器,定时器ID是储存在函数的tId属性中的。定时器代码{2}使用call来确保方法在适当的环境中执行。如果没有给出第二个参数,那么就在全局作用域内执行该方法。

还是上面的例子,这次window.onresize不直接执行事件处理函数了。

window.onresize = function(){
    throttle(resizeDiv);
}

这样,多数情况下,用户察觉不到变化,但能够给浏览器节省很多计算。

关于事件节流函数的写法,网上还看到另一种方法,可以传入延时时间作为参数,使用了闭包,但是大同小异。
原文在这里

function throttle(method,delay){
    var timer=null;
    return function(){
        var context=this, args=arguments;
        clearTimeout(timer);
        timer=setTimeout(function(){
            method.apply(context,args);
        },delay);
    }
}

同时,那篇文章的作者提到了一个新需求,我觉得也挺实用,就是在函数节流的基础上间隔固定时间就执行一次。
上代码:

function throttle(method,delay,duration){
    var timer=null, begin=new Date();       //{1}
    return function(){
        var context=this, args=arguments, current=new Date();
        clearTimeout(timer);
        if(current-begin>=duration){        //{2}
             method.apply(context,args);
             begin=current;
        }else{
            timer=setTimeout(function(){
                method.apply(context,args);
            },delay);
        }
    }
}

在{1}处多设置了一个开始时间,然后在每次调用的时候判断当前时间是否有超过预设的时间间隔,如果超过了,就立即执行一次事件处理函数,然后再将当前时就按记录下来,如此往复。

图片懒加载

在页面需要加载的图片很多的情况下,如果一次将所有的图片全部加载出来,会耗很长的时间,实际的页面呈现效果肯定不会很理想,所以我们就等到图片滚动到视口内后,再去对图片进行加载。

懒加载思路:将页面里所有img属性src属性用data-xx代替,当页面滚动直至此图片出现在可视区域时,用js取到该图片的data-xx的值赋给src。

我们这时候首先遇到一个问题,怎么去判断图片是不是进入了视口呢?于是,JS取各种高度的方法就派上用场了。

网页可见区域宽: document.body.clientWidth;
网页可见区域高: document.body.clientHeight;
网页可见区域宽: document.body.offsetWidth (包括边线的宽);
网页可见区域高: document.body.offsetHeight (包括边线的宽);
网页正文全文宽: document.body.scrollWidth;
网页正文全文高: document.body.scrollHeight;
网页被卷去的高: document.body.scrollTop;
网页被卷去的左: document.body.scrollLeft;
网页正文部分上: window.screenTop;
网页正文部分左: window.screenLeft;
屏幕分辨率的高: window.screen.height;
屏幕分辨率的宽: window.screen.width;
屏幕可用工作区高度: window.screen.availHeight;

除了这些难记的属性之外,还要考虑各个浏览器的兼容问题,就拿网页被卷上去的高来举例

IE6/7/8/9/10:
对于没有doctype声明的页面里可以使用 document.body.scrollTop 来获取 scrollTop高度 ;
对于有doctype声明的页面则可以使用 document.documentElement.scrollTop ;

Safari:
safari 比较特别,有自己获取scrollTop的函数 : window.pageYOffse t;

Firefox:
直接用 document.documentElement.scrollTop ;

所以,兼容性的写法就该是:

var srcollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;

有了这些知识,一个图片懒加载的代码就可以写了,先假定文档结构如下:


    

接下来就是我们加载图片的代码了,思路就是上面所说的,当图片进入视口后,从图片的data-src中取值,然后赋给src属性,完成图片的加载。

这里onscroll被触发了好多次,我们不妨用一下上面提到的函数节流。使用闭包的那种写法,修改上面代码中的一处:

window.onscroll = throttle(showImg,200);

这差不多就是一个带函数节流的图片懒加载的解决方法了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/88662.html

相关文章

  • 函数节流图片加载

    摘要:然而,如果前一个定时器尚未执行,其实就是替换为一个新的定时器,目的是只有在执行函数的请求停止了一段时间后才执行。首先清除之前设置的任何定时器,定时器是储存在函数的属性中的。 导读 这篇文章中主要介绍一下函数节流,然后给了一个图片懒加载的例子,说图片懒加载的时候顺带提了下怎么使用JS获取页面的宽高,卷上去的长度等。参考来源主要是《JavaScript高级程序设计》。 函数节流 浏览器的D...

    smallStone 评论0 收藏0
  • 手摸手-100行代码自己动手写个功能完整的图片加载插件

    摘要:景科同学的想法很简单,因为本人目前还是一个前端小白,只有通过不断的写,不断的学,在与的相爱相杀中才能更快速的进步。本项目是景科同学自写自测,虽然比较简单,但是不保证没有隐藏的。所以如果看官同学发现还望留言指正,景科同学在此以示感谢。 showImg(https://segmentfault.com/img/remote/1460000014251310?w=841&h=630); 本文...

    CompileYouth 评论0 收藏0
  • 前端笔记(二) 对象的深浅拷贝,函数的防抖与节流函数柯里化 ,图片的预加载加载

    摘要:对象是无法通过这种方式深拷贝。这就是函数防抖和节流要做的事情。函数防抖当触发频率过高时函数基本停止执行而函数节流则是按照一定的频率执行事件。 对象的深浅拷贝 对象的深拷贝与浅拷贝的区别: 浅拷贝:仅仅复制对象的引用, 而不是对象本身。 深拷贝:把复制的对象所引用的全部对象都复制一遍 浅拷贝的实现: var obj = { age : 18, person : { ...

    dongxiawu 评论0 收藏0
  • 实现图片加载(lazyload)

    摘要:当页面图片很多时,页面的加载速度缓慢,几钟内页面没有加载完成,也许会失去很多的用户。指向一张默认的图片,否则当为空时也会向服务器发送一次请求。这样便实现了懒加载。我想实现限制触发频率,来优化性能。 本文标题:实现图片懒加载(lazyload)文章作者:Jake发布时间:2016-11-26, 18:46:34最后更新:2016-11-28, 17:12:59原始链接:http://i....

    renweihub 评论0 收藏0
  • 实现图片加载(lazyload)

    摘要:当页面图片很多时,页面的加载速度缓慢,几钟内页面没有加载完成,也许会失去很多的用户。指向一张默认的图片,否则当为空时也会向服务器发送一次请求。这样便实现了懒加载。我想实现限制触发频率,来优化性能。 本文标题:实现图片懒加载(lazyload)文章作者:Jake发布时间:2016-11-26, 18:46:34最后更新:2016-11-28, 17:12:59原始链接:http://i....

    Developer 评论0 收藏0

发表评论

0条评论

tomlingtm

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<