图片的懒加载

背景:如果不使用懒加载,页面加载后,列表内所有的图片均会被浏览器加载,消耗资源,用户体验非常差,懒加载是性能优化的基础之一。

想做的就是让图片按需加载,触发滚动时遍历图片检测图片位置,若在可视区内则显示。

另外了解一下:
window.onload()--等待网页中所有内容加载完毕之后(包括图片)才能执行。
jQuery中$(docoment).ready --在网页所有的DOM结构绘制完毕就执行,可能DOM元素关联的东西并没有加载完。

1.改变图片的src(见4的优化)

监听最外层div的滚动事件,触发滚动时遍历图片检测图片位置,若在可视区则显示。

// template:
 <div @scroll="lazyLoad" ref="lazy">
    <img v-for="(src, index) in imgs" src="##" :dataSrc="src" :key="index">
         <!--more img-->
 </div>

// methods:
loadImg () {
   var img = this.$ref.lazy.getElementsByClassName("lazyImg");
        //已滚动高度+可视区高度
    var top = this.$refs.lazy.scrollTop + this.$refs.lazy.clientHeight;

    for(var i=0 ; i<img.length; i++){
        if(img[i].offsetTop <= top) {
            img[i].src = img[i].getAttribute('data-src')
        }
    }
}
lazyLoad () {
    this.LoadImg()
}

图片的src属性为空,使用data-src属性写上需要加载的图片的路径url,在懒加载的代码中,将src属性的值替换成对应的data-src。

2. vue中使用vue-lazyload

2.1 安装

npm -i vue-lazyload -S
或者引入CDN: https://unpkg.com/vue-lazyload/vue-lazyload.js

2.2 使用

main.js

import Vue from 'vue'
import VueLazyload from 'vue-lazyload'

Vue.use(VueLazyload)
// or with options
Vue.use(VueLazyload, {
   preLoad: 1.3,
   error: 'dist/error.png',
   loading: 'dist/loading.gif' //项目存放图片的路径
   attempt: 1
})

template:

<ul>
    <li v-for="img in list">
        <img v-lazy="img.src">
    </li>
</ul>

use v-lazy-container work with raw HTML and custom error and loading placeholder image

 <div v-lazy-container="{ selector: 'img', error: 'xxx.jpg', loading: 'xxx.jpg' }">
    <img data-src="//domain.com/img1.jpg">
    <img data-src="//domain.com/img2.jpg">
    <img data-src="//domain.com/img3.jpg">  
  </div>

2.3 了解属性:

key description default options
preLoad 预载的高度比例 1.3 Number
error 加载失败时src 'data-src' String
loading 加载图片时src 'data-src' String
attempt 常识次数 3 Number
listenEvents 监听的事件 ['scroll', 'wheel', 'mousewheel', 'resize', 'animationend', 'transitionend', 'touchmove']
adapter 动态修改element属性 { }
filter 图像的侦听器过滤器 { }
lazyComponent 延迟加载组件 false
dispatchEvent 触发dom事件 false Boolean
throttleWait 200 Number
observer false Boolean
observerOptions { rootMargin: '0px', threshold: 0.1 }
silent true Boolean

2.4 CSS state

<img src="imgUrl" lazy="loading">
<img src="imgUrl" lazy="loaded">
<img src="imgUrl" lazy="error">
<style>
    img[lazy=loading] {
        /*your style here*/
    }
    img[lazy=error] {
        /*your style here*/
    }
    .yourclass[lazy=loading] {
        /*your style here*/
    }
</style>

2.5 效果图

正在加载的图片们

3. 拓展:各种宽高

页可见区域宽: 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;

4.优化1

监听滚动事件,在滚动过程会不断触发lazyLoad对图片做一个遍历并判断,那么就会做无数次for循环,修改一次src会发送一个请求,在滚动的时候for循环每次都从头判断并修改src请求图片,那么请求次数可想而知。

函数防抖

如果在滚动过程中不断触发遍历并判断图片是否在可视区的监听事件,会耗费很大的性能,这里采用函数防抖:当用户停止滚动时统一遍历判断图片位置

debounce(fn) {
    // 函数防抖:用户停止操作之后触发
    clearTimeout(this.timer);
    this.timer = setTimeout(() => {
        fn();
    }, 1000);
}
// 将加载图片的方法放在debounce中
lazyLoad() {
    this.debounce(this.loadImg);
}

当用户滚动页面时,松开手才会执行loadImg来遍历判断图片位置。

又出现了一个问题:如果用户在滚动时从页面底部上拉到顶部一直没有松手,那么在这期间都不会执行loadImg,这意味着页面的图片都不会显示,非常影响用户体验

防抖优化

若用户上拉高度大于500px 那就自动加载一次可视区内图片,当用户下拉时并不需要执行。

lazyLoad () {
    // 如果上拉距离大于500px则自动加载
    if(this.$refs.lazy.scrollTop - this.oldScrollTop > 500) {
        this.loadImg();
        this.oldScrollTop = this.$refs.lazy.scrollTop;
    } else if(this.$refs.lazy.scrollTop - this.oldScrollTop < 0) {  // 如果向下拉则不做操作
        return ;
    } else {  // 如果向下拉但小于500px则防抖加载
        this.debounce(this.loadImg);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 背景和原理   浏览器在解析网页时会解析整个HTML代码,一般情况下,浏览器会请求其中所有的图片并把它们都下载下来...
    Gettingjie阅读 222评论 0 2
  • 一、原理 在浏览器滚动的时候,遍历所有图片,若图片在视窗可视区域,则加载该图片 将图片地址存放在自定义属性中(da...
    饥人谷_js_chen阅读 646评论 0 4
  • 我们做一个网站的时候,有时候有很多的资源加载,比如说有大量的图片展示,图片一般情况下会消耗很多的资源,一个页面有上...
    郑宋君阅读 280评论 0 0
  • 也许你看到这个标题第一个想法就是,这不是 h5 同事去做的事吗,直接给个 url 地址,我们直接加载就行了。但是这...
    被风扬起的沙阅读 4,563评论 3 3
  • 采用JavaScript 获取到所有的img标签,然后遍历获取到原有的src内容,置换为占位图,在onload事件...
    神采飞扬_2015阅读 1,816评论 0 2