jQuery实现图片懒加载

一、懒加载

1.什么是懒加载

目前,网络上各大论坛,尤其是一些图片类型的网站上,在图片加载时均采用了一种名为懒加载的方式,具体表现为,当页面被请求时,只加载可视区域的图片,其它部分的图片则不加载,只有这些图片出现在可视区域时才会动态加载这些图片,从而节约了网络带宽和提高了初次加载的速度。

2.懒加载的原理

页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片,只有通过javascript设置了图片路径,浏览器才会发送请求。

懒加载的原理就是先在页面中把所有的图片统一使用一张占位图进行占位,把正真的路径存在元素的自定义属性“data-src”(这个名字起个自己认识好记的就行)里,要用的时候就取出来,把它的值赋值给img的src属性。

二、获取屏幕高度:jquery的height()和javascript的height

1、jquery的各种高度 首先来说一说$(document)和$(window),如下:

$(document).height();//整个网页的高度
$(window).height();//浏览器可视窗口的高度
$(window).scrollTop();//浏览器可视窗口顶端距离网页顶端的高度(垂直偏移)

用一句话理解就是:当网页滚动条拉到最低端时,

$(document).height() == $(window).height() + $(window).scrollTop()

注意,是拉到最低端!

当网页高度不足浏览器窗口时$(document).height()返回的是$(window).height()

假如您要获取整个网页的高度,不建议用$("html").height()$("body").height()的高度,

原因:

$("body").height():body可能会有边框,获取的高度会比$(document).height()小; $("html").height():在不同的浏览器上获取的高度的意义会有差异,说白了就是浏览器不兼容。

说道这里,提及边框和margin还有padding,我们自然想到了jquery的另外的两个高度,那就是innerHeight()outerHeight()

innerHeight()outerHeight()不适用于window 和 document对象,对于window 和 document对象可以使用.height()代替。innerHeight()outerHeight()主要用来获取标签的高度。

在jQuery中,获取元素高度的函数有3个,它们分别是height()、 innerHeight()、 outerHeight()。

与此相对应的是,获取元素宽度的函数也有3个,它们分别是width()、 innerWidth()、 outerWidth()。这三个函数获取的是元素的高度,而不是元素到页面顶部的高度,要获取元素到页面顶部的高度可以用offset().top

以height()、innerHeight()、outerHeight()3个函数为例,来详细介绍它们之间的区别。

下面以元素element的盒模型为例来介绍它们之间的区别。

image.png

image.png

  1. 只有height()函数可用于window或document对象。
  2. "支持写操作"表示该函数可以为元素设置高度值。
  3. 1.4.1+ height()新增支持参数为函数(之前只支持数值)。
  4. 1.8.0+ innerHeight()支持参数为数值或函数。

jquery高度,放到浏览器中试一下

alert($(window).height());                           //浏览器当前窗口可视区域高度
alert($(document).height());                        //浏览器当前窗口文档的高度
alert($(document.body).height());                //浏览器当前窗口文档body的高度
alert($(document.body).outerHeight(true));  //浏览器当前窗口文档body的总高度 包括border padding margin
alert($(window).width());                            //浏览器当前窗口可视区域宽度
alert($(document).width());                        //浏览器当前窗口文档对象宽度
alert($(document.body).width());                //浏览器当前窗口文档body的宽度
alert($(document.body).outerWidth(true));  //浏览器当前窗口文档body的总宽度 包括border padding margin

javascript的各种高度

网页可见区域宽[仅针对body]: document.body.clientWidth
网页可见区域高[仅针对body]: document.body.clientHeight
网页可见区域宽[仅针对body]: document.body.offsetWidth (包括滚动条和边框,若滚动条和边框为0,则和clientWidth相等)
网页可见区域高[仅针对body]: document.body.offsetHeight (包括滚动条和边框,若滚动条和边框为0,则和clientHeight相等)
可视窗口宽度(包括滚动轴宽度):window.innerWidth; //IE9+、Chrome、Firefox、Opera 以及 Safari
可视窗口高度,不包括浏览器顶部工具栏: window.innerHeight;//IE9+、Chrome、Firefox、Opera 以及 Safari
网页正文全文宽(不包括滚动轴的宽度): document.body.scrollWidth
网页正文全文高:document.body.scrollHeight
//假如网页中没有滚动轴,document.body.scrollWidth和window.innerWidth相等,document.body.scrollHeight和window.innerHeight相等。
获取滚动条的滚动高度值:document.documentElement.scrollTop
获取滚动条的滚动高度值: document.body.scrollTop
获取滚动条的滚动宽度值: document.body.scrollLeft
网页正文部分上: window.screenTop
网页正文部分左: window.screenLeft
屏幕分辨率的高(整个屏幕的高度): window.screen.height
屏幕分辨率的宽(整个屏幕的宽度): window.screen.width
屏幕可用工作区高度: window.screen.availHeight
屏幕可用工作区宽度: window.screen.availWidth
整个浏览器可用工作区高度: window.outerHeight
整个浏览器可用工作区宽度: window.outerWidth

获取scrollTop兼容各浏览器的方法,以及body和documentElement是啥?

三、如何判断一个元素是否出现在窗口可视范围(浏览器的上边缘和下边缘之间,肉眼可视)。写出一个函数isVisible实现

function isVisible($img){
  //获取浏览器窗口高度
  var windowHeight = $(window).height(),
  //获取窗口滚动的高度
        windowScrolltop = $(window).scrollTop(),
  //获取图片到页面顶部的高度
        imgOffsettop = $img.offset().top,
   //获取图片元素自己的高度,包括内外边距
        imgHeight = $img.outerHeight(true);
  if(windowHeight + windowScrolltop > imgOffsettop && imgOffsettop + imgHeight > windowScrolltop){
    return true
  }
  return false 
}

四、当窗口滚动时,判断一个元素是不是出现在窗口可视范围。每次出现都在控制台打印 true 。用代码实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        body{
            background: pink;
            padding: 30px;
            height: 1800px;
        }
        #hello{
            position: absolute;
            top: 1200px;
            left: 40%;
            padding: 50px;
            border: 2px solid red;
            background: yellow;
        }      
    </style>
</head>
<body>
    <p id="hello">hello</p>
    <script src="https://code.jquery.com/jquery-3.1.0.js"></script>
    <script>
       $(window).on('scroll',function result(){
            if(isVisible($('#hello'))){
                console.log(true);
            }
            else{
                console.log(false);
            }
        }) 
        function isVisible($img){
            var windowHeight = $(window).height(),
                windowScrolltop = $(window).scrollTop(),
                imgoffsetTop = $img.offset().top,
                imgHeight = $img.outerHeight(true);
            if(windowHeight + windowScrolltop > imgoffsetTop && windowScrolltop < imgoffsetTop + imgHeight ){
                return true;
            }
            else {
                return false;
            }
        }
    </script>
</body>
</html>

效果展示

五、当窗口滚动时,判断一个元素是不是出现在窗口可视范围。在元素第一次出现时在控制台打印 true,以后再次出现不做任何处理。用代码实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        body{
            background: pink;
            padding: 30px;
            height: 1800px;
        }
        .p{
            position: absolute;
            top: 1200px;
            left: 40%;
            padding: 50px;
            border: 2px solid red;
            background: yellow;
        }      
    </style>
</head>
<body>
   <p class="p">hello</p>
   <script src="https://cdn.bootcss.com/jquery/1.9.1/jquery.js"></script>
   <script>
      var isShow=false;
      $(window).on('scroll',function result(){
        if(!isShow && isVisible($('.p'))){
          console.log(true);
        }
      }) 
      function isVisible($img){
        var windowHeight = $(window).height(),
            windowScrolltop = $(window).scrollTop(),
            imgoffsetTop = $img.offset().top,
            imgHeight = $img.outerHeight(true);
        if(windowHeight + windowScrolltop > imgoffsetTop && windowScrolltop < imgoffsetTop + imgHeight ){
          isShow=true;
          return true;
        } 
        return false;
      }
    </script>
</body>
</html>

效果展示

6、使用jQuery实现懒加载

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    ul,li{
      list-style:none;
    }
    .container{
      width: 600px;
      margin: 0 auto;
    }
    .container li{
      float: left;
      margin: 10px 10px;
    }
    .container li img{
      width: 240px;
      height: 180px;
    }
  </style>
</head>
<body>
    <ul class="container clearfix">
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>  
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>
        <li><a href="">![](http://upload-images.jianshu.io/upload_images/1969310-00fe161fe69693cf.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a></li>

    </ul>
    <script src="https://cdn.bootcss.com/jquery/1.9.1/jquery.js"></script>
    <script>
        /*
        大体思路:
        1.对于所有的img标签,把真实的地址放入自定义属性data-img
        2.当滚动页面时,检查页面所有的img标签,看看这个标签是否出现到我们的视野,当出现在我们的视野时
        再去判断它是否已经加载过,如果没有加载,加载它
        */

        
        // 用户第一次打开页面,还未滚动窗口的时候需要执行一次 lazyRender
        lazyRender();

        var clock;
        $(window).on('scroll',function(){
             //用户鼠标滚轮滚动一次,有多次事件响应。下面的 setTimeout 主要是为性能考虑,只在最后一次事件响应的时候执行 lazyRender,若在300毫秒内再次滚动则清除原来的定时器
            if(clock){
                clearTimeout(clock)
            }
            clock = setTimeout(function(){
                lazyRender();
            }, 300)
            
        })


        function lazyRender() {
            $('.container img').each(function(){
                //判断图片是否出现在可视窗口和图片是否已经加载
                if( checkShow($(this)) && !isLoaded($(this)) ){
                    //若图片出现在可是区域且没有加载,加载图片
                    loadImg($(this))
                }
            })
        }

        //判断图片出没出现在可视窗口
        function checkShow($img) {
          //获取浏览器窗口高度
          var windowHeight = $(window).height(),
          //获取窗口滚动的高度
              windowScrolltop = $(window).scrollTop(),
          //获取图片到页面顶部的高度
              imgOffsettop = $img.offset().top,
          //获取图片元素自己的高度,包括内外边距
              imgHeight = $img.outerHeight(true);
          if(windowHeight + windowScrolltop > imgOffsettop && imgOffsettop + imgHeight > windowScrolltop){
            return true
          }
          return false 
        }

        //判断图片加没加载过
        function isLoaded($img) {
          return $img.attr('data-src') === $img.attr('src')
        }
                
        //加载图片
        function loadImg($img) {
            $img.attr('src',$img.attr('data-src'))
        }
    </script>
</body>
</html>

效果展示

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端说吧

CSS-垂直|水平居中问题的解决方法总结

3376
来自专栏河湾欢儿的专栏

兼容问题(下)

每个浏览器不同的内核,不同的处理引擎,不同的渲染引擎就会导致写同一条样式的时候出现差异 这个现象叫做做兼容

672
来自专栏成长道路

表格展示+多余数据省略+鼠标悬浮显示

本人非专业前端,写的不好还望多多指教 1.首先需要将需要这样处理的td,th设置一下样式     text-align: center; /*设置水平居中*/ ...

2050
来自专栏NewbieWeb

移动端网页绝对自适应方案总结

网页自适应是个涵盖很广的话题,这里我只简单总结下移动端网页绝对自适应,简单来说如果设计师提供给你的设计稿是750px宽,此时里边有一张图片宽高均为375px;那...

641
来自专栏前端儿

Flex 布局相关用法

布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如,垂直居中 就不容易...

861
来自专栏小李刀刀的专栏

[译]clearfix改良及overflow:hidden详解

原文:clearfix Reloaded + overflow:hidden Demystified clearfix 和 overflow:hidden 可算...

3488
来自专栏前端说吧

JS - 兼容到ie7的自定义样式的滚动条封装

1054
来自专栏行者常至

java 自定义注解之ElementType.PARAMETER

392
来自专栏九彩拼盘的叨叨叨

滑动到底部无限加载的实现

我们常常会碰到数据条数很多,需要分页显示的情况。对于移动端页面,我们一般会用每次滚动到接近页面底部时,加载更多(下一页)数据的方式。本文就来介绍下滑动到底部无限...

452
来自专栏用户2442861的专栏

清除过的浮动

http://www.iyunlu.com/view/css-xhtml/55.html

522

扫码关注云+社区