json,异步加载js

925 阅读4分钟

part1.什么是json

  1. json是作用在前后端数据传输的对象(但是与前面学的对象本质上有区别对象是本地用的,json是用来传输的),为了与之前的对象加以区别我们规定将对象的属性名强制性加上双引号。
  2. json内部有两个方法。JSON.stringfy()是将json转为该对象的字符串,Json.parse()将字符串转换成json

part2.异步加载js

深度遍历的dom树的解析(生成)不等于dom树的加载完毕,生成只是单纯的结点加载完包括结点里面的内容,解析和加载这是一个异步的过程,css树+dom树=rander树,即渲染树。
渲染树可能会发生重排浪费效率,触发重排reflow的情况:
  - dom树节点的添加删除
  - dom结点的宽高位置变化,display
  - offsetwith和offsetleft
  渲染树还会产生重绘,也会降低渲染的效率,但是相对较少。
  1. 同步加载与异步加载 js修改主页面,会阻塞html和css(同步加载阻塞) 但是有的js包是工具包作用,所以有时候需要非阻塞的异步加载,下载js的同时对后续页面进行处理一遍加载一边加载html。如按需加载脚本文件中需要异步加载。 总之异步产生的原因是优化效率
  2. 异步加载js的三种方案
  • 方法1:defer异步加载,等到dom文件全部被解析完dom树生成才能被执行,只有IE能用。也可以将js语句写到内部也可以外部引用js包 代码演示:
    <script defer = "defer" src=“tools.js”> var a = 0;<script>
    
  • 方法2:aysnc异步加载,只能够外部引用脚本文件,js被加载完就执行。script标签里面不能写js的语句,ie9以上的都能用,现在通用的表达。 代码演示:
    <script aysnc = "aysnc"> var a = 0;<script>
    
扩充:ajax(asychronous异步 JavaScript and xml)
  • 方法3:创建script,插入到dom中,加载完毕后callback回调函数。该方法可以实现按需加载比如一个页面里面有100个按钮,什么情况下按哪一个按钮。可能出现的情况当script标签被添加到页面里面或函数执行完的时候,脚本文件还没有加载完,这个时候会报错,那什么时候能够执行呢?所以需要一个监听load事件的机制。 代码演示:
<script >
    function loadScript(url, callback) {
     //在script标签里面创建一个script标签
     var script = document.createElement('script');
     script.type = "text/javascript";
     //ie
     if(script.readyState) {
         script.onreadyStateChange = function() {
          if(script.readyState == "complete"|| script.readyState == "loaded"){
            callback();
          }
         }
     }
     //chrome firefox opera safira
     else{
       script.onload = function() {
           callback();
       }
     }
     //加载js包的语句放在后面是为了能够有效地捕获到加载的事件来触发,事件的触发依赖于loading到load的过程,不能加载完毕之后再绑定点击事件
     script.src = url;
     document.head.append(script);
    }
    //注意传递的第二个参数是函数声明不是函数
    loadScript(demo.js, function(){test();} );
    </script>

脚本文件没有被加载,那么里面的函数也没有被加载,解决传入未定义的函数除了上面的方法外还有另外一种方法,是与函数库相配合来按需加载,比如有一个函数库

var obj = {
    test : function() {
        ...
    },
    demo : function() {
        ...
    },
    haha : function() {
        ...
    }

}

loadscript函数变成:

<script >
    function loadScript(url, callback) {
     //在script标签里面创建一个script标签
     var script = document.createElement('script');
     script.type = "text/javascript";
     //ie
     if(script.readyState) {
         script.onreadyStateChange = function() {
          if(script.readyState == "complete"|| script.readyState == "loaded"){
            obj[callback]();
          }
         }
     }
     //chrome firefox opera safira
     else{
       script.onload = function() {
           obj[callback]();
       }
     }
     //加载js包的语句放在后面是为了能够有效地捕获到加载的事件来触发,事件的触发依赖于loading到load的过程,不能加载完毕之后再绑定点击事件
     script.src = url;
     document.head.append(script);
    }
    
    loadScript(demo.js, "test" );
    </script>

上面的demo只是为了弄清楚思想,可以进行一些更改比如加载完后想要执行一系列方法可以传回调函数数组。

  • ==遇到的问题== question:函数库obj是怎么传递进去的? answer:想了很久我觉得是函数function
function() {
        obj[callback]();
    }

里面的 objcallback;语句是在加载完毕后才执行,也就是script.src=url执行之后再回到里面的if-else中,此时已经存在obj。

part3.js加载时间线

  1. 先生成document代表js可以运行了。documen.readyState='loading'
  2. 文档解析完了,dom树解析完了。遇到link,script,异步script如何解析。解析完后document.readyState= 'interactive'活跃的。
  3. 文档解析并加载完了 document.readyState= 'complete',window触发load事件。

part4 额外的东东

  1. 事件没有大小都是小写,便于和属性区别开来
  2. innerText和innerHtml区别,前者是获取指定标签的文本内容,后者是html内容包含HTML标签。