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

优化首屏体验

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>
相关推荐
神奇的程序员5 小时前
开发了一个管理本地开发环境的软件
前端·flutter
XiYang-DING6 小时前
HTML 核心标签
前端·html
Csvn6 小时前
技术选型方法论
前端
Csvn6 小时前
前端架构演进:从页面到平台的十年变革
前端
李伟_Li慢慢6 小时前
ShaderToy-山峦+蓝天+白云
前端·webgl
小码哥_常6 小时前
Android字体字重设置全攻略:XML黑科技+Kotlin动态实现,告别.ttf臃肿
前端
czlczl200209257 小时前
松散索引扫描/跳跃索引扫描
数据库·mysql·性能优化
言萧凡_CookieBoty8 小时前
AI 编程省 Token 实战:从 Spec、上下文工程到模型分层的降本策略
前端·ai编程
DFT计算杂谈8 小时前
wannier90 参数详解大全
java·前端·css·html·css3
铁皮饭盒9 小时前
第2课:5分钟!用 Trae AI 生成你的第一个后端服务(Bunjs + Elysia)
前端·后端·全栈