Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

js异步加载方式 #27

Open
TieMuZhen opened this issue Nov 20, 2021 · 0 comments
Open

js异步加载方式 #27

TieMuZhen opened this issue Nov 20, 2021 · 0 comments

Comments

@TieMuZhen
Copy link
Owner

TieMuZhen commented Nov 20, 2021

js动态添加script标签

(function(){
    var scriptEle = document.createElement("script");
    scriptEle.type = "text/javasctipt";
    scriptEle.async = true;
    scriptEle.src = "http://cdn.bootcss.com/jquery/3.0.0-beta1/jquery.min.js";
    var x = document.getElementsByTagName("head")[0];
    x.insertBefore(scriptEle, x.firstChild);       
 })();

但是这种加载方式执行完之前会阻止onload事件的触发,而现在很多页面的代码都在onload时还执行额外的渲染工作,所以还是会阻塞部分页面的初始化处理。

注意:
页面加载完成有两种事件:

  • ready事件:表示文档结构(DOM结构)已经加载完成(不包含图片等非文字媒体文件),
  • onload事件:指示页面包含图片等文件在内的所有元素都加载完成。(可以说:ready 在onload 前加载)

onload时的异步加载

(function(){
    if(window.attachEvent){
        window.attachEvent("load", asyncLoad);
    }else{
        window.addEventListener("load", asyncLoad);
    }
    var asyncLoad = function(){
        var ga = document.createElement('script');
         ga.type = 'text/javascript';
        ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0];
        s.parentNode.insertBefore(ga, s);
    }
})();

这种方法只是把插入script的方法放在一个函数里面,然后放在window的onload方法里面执行,这样就解决了阻塞onload事件触发的问题。

注: DOMContentLoadedload的区别。前者是在document已经解析完成,页面中的dom元素可用,但是页面中的图片,视频,音频等资源未加载完,DOMContentLoaded作用同jQuery中的ready事件;后者的区别在于页面所有资源全部加载完毕。

$(document).ready()

需要引入jquery,兼容所有浏览器

$(document).ready(function() {
     alert("加载完成!");
 });

<script>标签的async="async"属性

  • async属性规定一旦脚本可用,则会异步执行
  • async属性仅适用于外部脚本
  • 此方法不能保证脚本按顺序执行
  • 他们将在onload事件之前完成
  • async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。
<script type="text/javascript" src="xxx.js" async="async"></script>

对于async标记,浏览器的解析过程是这样的:

  • 浏览器开始解析HTML网页
  • 解析过程中,发现带有async属性的script标签
  • 浏览器继续往下解析HTML网页,同时并行下载script标签中的外部脚本
  • 脚本下载完成,浏览器暂停解析HTML网页,开始执行下载的脚本
  • 脚本执行完毕,浏览器恢复解析HTML网页

<script>标签的defer="defer"属性

  • defer要等到整个页面在内存中正常渲染结束,才会执行。
  • 兼容所有浏览器
  • 此方法可以确保所有设置了defer属性的脚本按顺序执行
<script type="text/javascript" defer></script>

对于defer标记,浏览器的解析过程是这样的:

  • 浏览器开始解析HTML网页
  • 解析过程中,发现带有defer属性的script标签
  • 浏览器继续往下解析HTML网页,同时并行下载script标签中的外部脚本
  • 浏览器完成解析HTML网页,此时再执行下载的脚本

es6模块type="module"属性

浏览器对于带有type=”module”<script>都是异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了<script>标签的defer属性 。如下:

<script type="module" src="XXX.js"></script>

ready()与onload()的区别

window.onload()(不推荐)

  • 加载时机: 必须等待网页全部加载完毕(包括图片等),然后再执行JS代码。
  • 执行次数: 只能执行一次,如果第二次,那么第一次的执行会被覆盖。
  • 简写: 无。
    举例:
window.onload = function() { console.log("text1");};
window.onload = function() { console.log("text2");}; 

// ƒ () { console.log("text2");}  // 结果只输出第二个

$(document).ready()

  • 加载时机: 只需要等待网页中的DOM结构加载完毕,就能执行JS代码。
  • 执行次数: 可以执行多次,不会覆盖上一次。
  • 简写:$(function () {})
    举例:
$(document).ready(function(){console.log("Hello")});
$(document).ready(function(){console.log("Hello")});

// Hello
// Hello

注意

asyncdefer这两个属性只是script标签在header标签中使用的,如果你把它放在body后面是无效的

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant