同步加载
默认的就是同步加载
<script src="http://yourdomain.com/script.js"></script>
同步加载: 同步模式又称阻塞模式,会阻止浏览器的后续处理,停止了后续的文件的解析,执行,如图像的渲染。流览器之所以会采用同步模式,是因为加载的js文件中有对dom的操作,重定向,输出document等默认行为,所以同步才是最安全的。通常会把要加载的js放到body结束标签之前,使得js可在页面最后加载,尽量减少阻塞页面的渲染。这样可以先让页面显示出来。
简单来说:js的网页中加载会阻塞到未加载的css,html的加载跟渲染
异步加载
异步加载又称非阻塞加载,浏览器在下载执行js的同时,还会继续进行后续页面的处理。主要有一下3种实现方式。。。async, await , document.createElement
1. async,defer
这个是 ES7 中的特性,async顾名思义是“异步”的意思,async用于声明一个函数是异步的。而await从字面意思上是“等待”的意思,就是用于等待异步完成。
首先,这两个都只能用于 script 外链文件的形式,不能把代码写到标签里
<script async>console.log("1")</script>
<script defer>console.log("2")</script>
上面两种形式是无效的,还是同步执行代码
先放个熟悉的图~
蓝色线代表网络读取,红色线代表执行时间,这俩都是针对脚本的;绿色线代表 HTML 解析。
defer
<script src="1.js" defer></script>
<script src="2.js" defer></script>
<script src="3.js" defer></script>
defer 属性表示延迟执行引入 JavaScript,即 JavaScript 加载时 HTML 并未停止解析,这两个过程是并行的。
整个 document 解析完毕且 defer-script 也加载完成之后(这两件事情的顺序无关),会执行所有由 defer-script 加载的 JavaScript 代码,再触发 DOMContentLoaded 事件。
defer 不会改变 script 中代码的执行顺序,示例代码会按照 1、2、3 文件 的顺序执行。
所以,defer 与相比普通 script,有两点区别:
载入 JavaScript 文件时不阻塞 HTML 的解析
执行阶段被放到 HTML 标签解析完成之后。
async
async 属性表示异步执行引入的 JavaScript,与 defer 的区别在于,如果已经加载好,就会开始执行,无论此刻是 HTML 解析阶段还是 DOMContentLoaded 触发(HTML解析完成事件)之后。需要注意的是,这种方式加载的 JavaScript 依然会阻塞 load 事件。换句话说,async-script 可能在 DOMContentLoaded 触发之前或之后执行,但一定在 load 触发之前执行。
从上一段也能推出,多个 async-script 的执行顺序是不确定的,谁先加载完谁执行。值得注意的是,向 document 动态添加 script 标签时,async 属性默认是 true。
这里说明一下 DOMContentLoaded 事件 和 load 时间 触发时机:
· 文档解析完毕,页面重新渲染。当页面引用的所有 js 同步代码执行完毕,触发 DOMContentLoaded 事件。
· html 文档中的图片资源,js 代码中有异步加载的 css、js 、图片资源都加载完毕之后,load 事件触发。
2. 动态创建DOM
在script标签内,使用 document.creatElements 创建的 ** script **默认是异步的。
<script type="text/javascript">
2 (function() {
3 var s = document.createElement('script');
4 s.type = 'text/javascript';
5 s.async = true; //这句可以删除,但是效果不变。
6 s.src = 'js/a.js';
7 var x = document.getElementsByTagName('script')[0];
8 x.parentNode.insertBefore(s, x);
9 })();
10 </script>
注意:这种方法会阻止onload事件,比如下面的代码,会等到a.js中的弹出框弹出后再执行
<script type="text/javascript">
2 window.onload=function(){
3 document.getElementById('div').innerHTML="onload完成"
4 }
5 </script>
6 //写在html中
上面问题解决方案如下
把插入script的方法放在一个函数里面,然后放在window.onload方法里面执行,这样就解决了阻塞onload事件触发的问题.
(function() {
2 function async_load(){
3 var s = document.createElement('script');
4 s.type = 'text/javascript';
5 s.async = true;
6 s.src = 'js/yibujiaz.js';
7 var x = document.getElementsByTagName('script')[0];
8 x.parentNode.insertBefore(s, x);
9 }
10 if (window.attachEvent)
11 window.attachEvent('onload', async_load);
12 else
13 window.addEventListener('load', async_load, false);
14 })();
DOMContentLoaded与onload事件不同,DOMContentLoaded是页面解析完成,页面的dom元素可以使用,但是页面的图片、视频等资源可能还没加载完成
延迟加载(懒加载)lazy-load
有些代码在某种特定情况下才需要,并不是一股脑子都加载出来了,这个时候就需要延迟加载;
使用场景:很多网站页面上图片很多,页面很长,这中情况下就可以使用懒加载;用户点开页面的瞬间,呈现给他的只有屏幕的一部分(我们称之为首屏)。只要我们可以在页面打开的时候把首屏的图片资源加载出来,用户就会认为页面是没问题的。至于下面的图片,我们完全可以等用户下拉的瞬间再即时去请求、即时呈现给他。这样一来,性能的压力小了,用户的体验却没有变差——这个延迟加载的过程,就是 Lazy-Load。
实现原理
页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片,只有通过javascript设置了图片路径,浏览器才会发送请求。
懒加载的原理就是先在页面中把所有的图片统一使用一张占位图进行占位,把正真的路径存在元素的“data-url”(这个名字起个自己认识好记的就行)属性里,要用的时候就取出来,再设置;
实现步骤
1)首先,不要将图片地址放到src属性中,而是放到其它属性(data-original)中。
2)页面加载完成后,根据scrollTop判断图片是否在用户的视野内,如果在,则将data-original属性中的值取出存放到src属性中。
3)在滚动事件中重复判断图片是否进入视野,如果进入,则将data-original属性中的值取出存放到src属性中。
懒加载的优点是什么?
页面加载速度快、可以减轻服务器的压力、节约了流量,用户体验好
预加载
提前加载图片,当用户需要查看时可直接从本地缓存中渲染
实现预加载的方式:
1:用CSS和JavaScript实现预加载
2:仅使用JavaScript实现预加载
3:使用Ajax实现预加载
注: link 标签设置 rel="preload" 可实现资源的异步预先加载
详情见连接:https://blog.csdn.net/ydw_ydw/article/details/81228556
懒加载和预加载的区别:两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载。懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力,不利于首屏渲染。预加载应用如广告弹窗等。