性能优化篇--优化首屏体验

优化首屏体验

Lazy-Load 初探

掘金首页采用了懒加载策略。当我们的页面并未滚动至包含图片的 div 元素所在的位置时,它的样式是这样的:

js 复制代码
<div data-v-b2db8566=""  
    data-v-009ea7bb=""  
    data-v-6b46a625=""  
    data-src="https://user-gold-cdn.xitu.io/2018/9/27/16619f449ee24252?imageView2/1/w/120/h/120/q/85/format/webp/interlace/1"  
    class="lazy thumb thumb"  
    style="background-image: none; background-size: cover;">  
</div>
  • 我们注意到 style 内联样式中,背景图片设置为了 none。也就是说这个 div 是没有内容的,它只起到一个占位的作用。
  • 一旦我们通过滚动使得这个 div 出现在了可见范围内,那么 div 元素的内容就会发生变化,呈现如下的内容:
js 复制代码
style="background-image: url(&quot;https://user-gold-cdn.xitu.io/2018/9/27/16619f449ee24252?imageView2/1/w/120/h/120/q/85/format/webp/interlace/1&quot;); background-size: cover;"

一起写一个 Lazy-Load

html 复制代码
<!DOCTYPE html>  
<html lang="en">  
<head>  
<meta charset="UTF-8">  
<meta >  
<meta http-equiv="X-UA-Compatible" content="ie=edge">  
<title>Lazy-Load</title>  
<style>  
    .img {  
        width: 200px;  
        height:200px;  
        background-color: gray;  
    }  
    .pic {  
        // 必要的img样式  
    }  
</style>  
</head>  
<body>  
    <div class="container">  
        <div class="img">  
            // 注意我们并没有为它引入真实的src  
            <img class="pic" alt="加载中" data-src="./images/1.png">  
        </div>  
        <div class="img">  
            <img class="pic" alt="加载中" data-src="./images/2.png">  
        </div>  
        <div class="img">  
            <img class="pic" alt="加载中" data-src="./images/3.png">  
        </div>  
        <div class="img">  
            <img class="pic" alt="加载中" data-src="./images/4.png">  
        </div>  
        <div class="img">  
            <img class="pic" alt="加载中" data-src="./images/5.png">  
        </div>  
        <div class="img">  
            <img class="pic" alt="加载中" data-src="./images/6.png">  
        </div>  
        <div class="img">  
            <img class="pic" alt="加载中" data-src="./images/7.png">  
        </div>  
        <div class="img">  
            <img class="pic" alt="加载中" data-src="./images/8.png">  
        </div>  
        <div class="img">  
            <img class="pic" alt="加载中" data-src="./images/9.png">  
        </div>  
        <div class="img">  
            <img class="pic" alt="加载中" data-src="./images/10.png">  
        </div>  
    </div>  
</body>  
</html>
  • 在懒加载的实现中,有两个关键的数值:一个是当前可视区域的高度 ,另一个是元素距离可视区域顶部的高度
  • 当前可视区域的高度 , 在和现代浏览器及 IE9 以上的浏览器中,可以用 window.innerHeight 属性获取。在低版本 IE 的标准模式中,可以用 document.documentElement.clientHeight 获取,这里我们兼容两种情况:
js 复制代码
const viewHeight = window.innerHeight || document.documentElement.clientHeight

元素距离可视区域顶部的高度 ,我们这里选用 getBoundingClientRect() 方法来获取返回元素的大小及其相对于视口的位置。对此 MDN 给出了非常清晰的解释:

返回的DOMRect 对象包含了一组用于描述边框的只读属性---------lefttoprightbottom,单位为像素。除了 widthheight 外的属性都是相对于视口的左上角位置而言的。

Lazy-Load 方法的实现:

html 复制代码
<script>  
    // 获取所有的图片标签  
    const imgs = document.getElementsByTagName('img')  
    // 获取可视区域的高度  
    const viewHeight = window.innerHeight || document.documentElement.clientHeight  
    // num用于统计当前显示到了哪一张图片,避免每次都从第一张图片开始检查是否露出  
    let num = 0  
    function lazyload(){  
        for(let i=num; i<imgs.length; i++) {  
            // 用可视区域高度减去元素顶部距离可视区域顶部的高度  
            let distance = viewHeight - imgs[i].getBoundingClientRect().top  
            
            // 如果可视区域高度大于等于元素顶部距离可视区域顶部的高度,说明元素露出  
            if(distance >= 0 ){  
                // 给元素写入真实的src,展示图片  
                imgs[i].src = imgs[i].getAttribute('data-src')  
                // 前i张图片已经加载完毕,下次从第i+1张开始检查是否露出  
                num = i + 1  
            }  
        }  
    }  
    // 监听Scroll事件  
    window.addEventListener('scroll', lazyload, false);  
</script>
相关推荐
小园子的小菜11 分钟前
接口性能优化实战:5大策略+落地案例
性能优化
遗憾随她而去.14 分钟前
前端首屏加载时间的度量:FCP、LCP等指标的规范理解
前端
CDwenhuohuo16 分钟前
安卓app巨坑 nvue后者页面要写画笔绘制功能nvue canvas
前端·javascript·vue.js
一只小bit22 分钟前
Qt 事件:覆盖介绍、处理、各种类型及运用全详解
前端·c++·qt·cpp
Ulyanov30 分钟前
大规模战场数据与推演:性能优化与多视图布局实战
开发语言·python·性能优化·tkinter·pyvista·gui开发
人道领域36 分钟前
JavaWeb从入门到进阶(前端工程化)
前端
晓风残月淡40 分钟前
高性能MYSQL(四):查询性能优化
数据库·mysql·性能优化
shughui1 小时前
APP、Web、H5、iOS与Android的区别及关系
android·前端·ios
Amumu121381 小时前
React Router 6介绍
前端·react.js·前端框架
郝学胜-神的一滴1 小时前
机器学习数据预处理:归一化与sklearn的MinMaxScaler详解
人工智能·python·程序人生·机器学习·性能优化·sklearn