时间线

1、时间线定义

定义:在浏览器加载页面开始的那一刻到页面加载完全结束的这个过程中,按照顺序发生的每一件事情的总流程,就是时间线。

(1)时间线产生过程:

1、页面加载就产生一个document对象 》 JS就起作用了 》 涉及到DOM功能体就生效了
2、解析文档:浏览器从HTML的第一行阅读到最后一行。 在解析的同时,涉及到DOM的会构建DOM树
        (1) document.readyState = 'loading' 文档加载中
3、遇到 link 开新线程,异步加载css外部文件 style 》 构建 CSSOM
4、没有设置异步加载的script,阻塞文档解析,等待 JS 脚本加载并执行完成后,继续解析文档
5、异步加载 script,异步加载 JS 脚本并且执行,不阻塞解析文档,但不能使用document.write(),
    如果一定要用,需要写在window.onload = function(){...}的函数中
6、解析文档遇到 img,先解析这个节点,只要写了src="",就先创建加载线程,异步加载图片资源,不阻塞解析文档
7、文档解析完成
        (2) document.readyState = 'interactive' 文档解析完成
8、文档解析完成之后,如果是defer script,JS脚本开始按照顺序执行。
9、文档解析完成之后,会触发 DOMContentLoaded 事件,
    程序:同步的脚本执行阶段 转为 事件驱动阶段,用户可以操作页面
10、async script 加载并执行完毕,img 等资源加载完毕,window 对象中的 onload 事件才触发
        (3) document.readyState = 'complete' 文档加载完成

(2)查看文档解析的三个状态变化

// 只要 readyState 状态发生变化就触发,浏览器JS引擎实时监听
console.log(document.readyState); // loading
document.onreadystatechange = function() {
    console.log(document.readyState); // interactive -> complete
}

(3)监听 DOMContentLoaded

// 监听 DOMContentLoaded:在'interactive' : 文档解析完成之后触发
document.addEventListener('DOMContentLoaded', function(){
    console.log('DOMContentLoaded');
}, false);

(4)window.onload 与 DOMContentLoaded 区别
window.onload:在文档加载完成之后触发
DOMContentLoaded:在文档解析完成之后触发

2、文档解析完毕方法兼容性 - 了解

function domReady(fn) {
    if (document.addEventListener) {
        // 绑定事件
        document.addEventListener('DOMContentLoaded', function(){
            // 清除事件
            document.removeEventListener('DOMContentLoaded', arguments.callee, false);
            // 执行函数
            fn();
        }, false);
    } else if (document.attachEvent) {
        // IE
        document.attachEvent('onreadystatechange', function(){
            if (this.readyState === 'complete') { // 因为有些IE浏览器interactive很快,所以用complete
                // 清除事件
                document.attachEvent('onreadystatechange', arguments.callee);
                // 执行函数
                fn();
            }
        });
    }

    // 兼容IE6-7低版本,并排除iframe
    if (document.documentElement.doScroll && typeof(window.frameElement) === 'undefined') {
        try {
            document.documentElement.doScroll('left');
        } catch(e) {
            return setTimeout(arguments.callee, 20);
        }
        fn();
    }
}