前端性能优化 — JS预加载和懒加载

JS预加载

需求:有时我们需要实现例如快速快速切换页面、图片之类的功能时,能尽快的加载出我们所需的图片会极大提升用户体验,这时用预加载将图片先缓存到浏览器,用户使用需显示图片时无疑会顺畅很多。

核心:当一个图片在其它地方被加载过,那么它就会存在于浏览器缓存中,用到它时可直接从本地缓存中渲染。

特点:增强用户的体验,但会加载服务器的负担。

实现方式:

1. CSS方式

通过css中设置background的方式将图片加载进缓存,写在任意标签下,设置background-position使其不可见

background: url("img.jpg") no-repeat -9999px -9999px;

2. JS方式

实现图片预加载

<div class="hidden">  
    <script type="text/javascript">   
            var images = new Array()  
            function preload() {  
                for (i = 0; i < preload.arguments.length; i++) {  
                    images[i] = new Image()  
                    images[i].src = preload.arguments[i]  
                }  
            }  
            preload(  
                "http://domain.tld/gallery/image-001.jpg",  
                "http://domain.tld/gallery/image-002.jpg",  
                "http://domain.tld/gallery/image-003.jpg"  
            )  
    </script>  
</div>

3. AJAX方式

实现CSS和JS预加载

window.onload = function() {  
    setTimeout(function() {  
        var xhr = new XMLHttpRequest();  
        xhr.open('GET', 'http://domain.tld/preload.js');  
        xhr.send();  
        xhr = new XMLHttpRequest();  
        xhr.open('GET', 'http://domain.tld/preload.css');  
        xhr.send();  
        // preload image  
        new Image().src = "http://domain.tld/preload.png";  
    }, 1000);  
};

JS懒加载

需求:试想当一个网页有非常多的图片时,那么加载整个页面的时间就会大量增加,对用户而言需要好几秒的时间加载一个页面无疑是不友好的。然而更多时候用户并不会浏览到全部加载进来的图片,所以当用户浏览到当前视口时再去加载相应的图片无疑是两全其美的选择。

核心:将当前可视区域的图片加载进来,监听滚动显示图片。

特点:页面加载速度快、可以减轻服务器的压力、节约了流量,用户体验好。

实现方式:

1. 动态设置img的src属性

1) 首先,不要将图片地址放到src属性中,而是放到其它属性(data-original)中。
2) 页面加载完成后,根据scrollTop判断图片是否在用户的视野内,如果在,则将data-original属性中的值取出存放到src属性中。
3) 在滚动事件中重复判断图片是否进入视野,如果进入,则将data-original属性中的值取出存放到src属性中。

这里有一个细节,当img的src为空时,仍然会对服务器发起一次请求,详情可参看:http://youngae520.lofter.com/post/28e9e5_a67a8a,因此使用此种方式往往会默认在src中写入一个小的图片作为默认图片。

<!DOCTYPE HTML>
<html>
    <head>
        <meta charset="UTF-8">
        <title>页面懒加载</title>
        <style>
            img {
                display: block;
                margin: 0 auto 50px;
                width: 960px;
                height: 540px;
            }
        </style>
    </head>
    <body>
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzutb8xegj31hc0u0k77.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzutz6y29j31hc0u0ak4.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzuu8igyyj31hc0u0qgv.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzuug47wrj31hc0u0k2q.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzuuowb0hj31hc0u0akx.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzuuyjapsj31hc0u0ths.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzutb8xegj31hc0u0k77.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzutz6y29j31hc0u0ak4.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzuu8igyyj31hc0u0qgv.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzuug47wrj31hc0u0k2q.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzuuowb0hj31hc0u0akx.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzuuyjapsj31hc0u0ths.jpg" alt="">        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzutb8xegj31hc0u0k77.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzutz6y29j31hc0u0ak4.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzuu8igyyj31hc0u0qgv.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzuug47wrj31hc0u0k2q.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzuuowb0hj31hc0u0akx.jpg" alt="">
        <img src="default.jpg" data-src="http://ww1.sinaimg.cn/large/005ODVHQgy1fuzuuyjapsj31hc0u0ths.jpg" alt="">
    </body>
    <script>
        var num = document.getElementsByTagName('img').length;
        var img = document.getElementsByTagName("img");
        // 存储图片加载到的位置,避免每次都从第一张图片开始遍历
        var n = 0;
        // 页面载入完毕加载可视区域内的图片
        lazyload();                                
        window.onscroll = lazyload;
        // 监听页面滚动事件
        function lazyload() {
            // 可见区域高度
            var seeHeight = document.documentElement.clientHeight;
            // 滚动条距离顶部高度
            var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            for (var i = n; i < num; i++) {
                if (img[i].offsetTop < seeHeight + scrollTop) {
                    if (img[i].getAttribute("src") == "default.jpg") {
                        img[i].src = img[i].getAttribute("data-src");
                    }
                    n = i + 1;
                }
            }
        }
    </script>
</html>

emmm......有没有发现这样写的问题......

好多代码啊~用户不一定会滚动到下面,而且JS中频繁的DOM操作仍然会影响性能~

2. innerHtml

考虑到上述问题,我就去京东主页上去偷学了一下他们咋实现的~

首先我们来看“频道广场”的下面有好多空的div(现在还没有滚动到那里~):

 而当我滚动到对应的地方时,再查看源代码:

发现不仅仅是这些显示图片的item里多了内容,其他的地方也多了很多东西,让我们随意看一个item:

多么熟悉的lazyimg出现了~~~~~~ 所以我怀疑这种做法是通过直接写innerHtml实现的,相比于第一种设置src属性的方法,首先刚开始加载的html就少了很多,那么页面渲染就会更快~ 其次直接写html也就避免了频繁的DOM操作。

 相关参考:

https://www.jianshu.com/p/5456a52e73e9

https://www.jianshu.com/p/c8a7c2019c09

https://www.cnblogs.com/leyan/p/6085148.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值