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

优化首屏体验

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>
相关推荐
小黑技术栈19 分钟前
关于前端的一些话
前端
无人生还39 分钟前
从 Vue3 到 React · 快速上手系列第 11 篇:状态管理
前端·vue.js·react.js
GuWenyue41 分钟前
90%前端写React TS都踩坑!一套父子组件+Hooks完整实战,彻底搞懂类型约束
前端·react.js
Hilaku1 小时前
当 AI 一天写完一周的代码,我们还剩什么优势?
前端·javascript·程序员
尘世中一位迷途小书童1 小时前
无人机航线里的云台角度怎么调?Cesium 做了个视锥 + 鹰眼联动
前端·javascript·数据可视化
思码梁田1 小时前
CSS display 属性:从元素类型转换到隐藏元素的实用指南
前端·css·display·inline·block·none·inline-block
Csvn1 小时前
⚡ Vite 依赖预构建(optimizeDeps)的 3 个经典坑:改了源码不生效、新增依赖 404、缓存怎么清都不行
前端
A24207349301 小时前
Vue3 + TypeScript:后端数据在表格内渲染后进行增删改的完整实现步骤
前端·javascript·typescript
他们叫我 悦儿遥遥雨1 小时前
.NET 8 Web开发入门(六):Blazor 全栈开发——告别 JavaScript 焦虑
前端·javascript·.net
用户2181697049301 小时前
Flutter(九)StatelessWidget StatefullWidget
前端