自己构建一个domReady.js

用过jQuery的人们想必对这句话都不陌生“$(document).ready(function(){ func(xxx)//执行函数}); “,还有两种表现形式就不一一列举了,这个其实就是jQuery的domReady函数,在进行dom操作的时候保证所有的dom元素完全被加载!
举个例子
  • 我们执行下面一段代码,让h1内的元素变红,按照下面的执行顺序显然是不可能的,简单的理解就是js在选择h1标签的时候,h1的dom结构还没有生成,当然如果稍作改动也是可以达到预期效果的,比如加一个window.onload函数,但是今天就不采用这种方式来解决,原因一会儿在进一步阐述。
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>
    <script type="text/javascript">
            document.getElementById("h1").style.color = "red";
    </script>
    <body id="box">
        <h1 id="h1">hhhhh</h1>
    </body>
</html>

html标签和dom节点之间的关系

出现上边那种情况就是没有理解html标签和dom节点之间的关系,html是一种标记语言,它告诉我们这个页面的内容,但是行为操作是需要通过dom操作来实现的。html标签通过浏览器解析后变成dom节点,当加载页面的时候dom节点会以dom tree的形式组织,当所有的dom节点都构建完毕,就可以理解为dom ready


html标签如何变成dom节点

浏览器通过渲染引擎来实现,它的作用就是把请求的内容渲染到页面上,默认情况下渲染引擎可以渲染html,xml,图片,但是也可通过插件来显示其他的文件,比如pdfviewer来显示pdf文档。


渲染流程
  • 首先解析html,构建dom树(构建dom节点)
  • 构建渲染树(解析样式信息)
  • 布局渲染树(布局dom节点)
  • 绘制渲染树(绘制dom节点)
webkit渲染流程图

window.onload
  • window.onload是等待页面所有dom节点加载完毕后在执行js代码,代码如下
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>
    <script type="text/javascript">
    window.onload = function(){
        document.getElementById("h1").style.color = "red";
    }
    </script>
    <body id="box">
        <h1 id="h1">hhhhh</h1>
    </body>
</html>

那为什么放弃window.onload呢,当页面结构不多的时候用window.onload是完全没有问题的。举个小例子吧,现在有这样的一个需求,在页面内请求100张远程加载的图片,并且要求点击图片的时候alert出图片地址,这时候会发现dom节点会很快的创建完毕,但是图片的资源可没有那么快的就能加载完毕,这时候页面就会出现问题,对用户体验大打折扣。


domReady实现
domReady实现策略
  • 1.支持DOMContentLoaded的事件,就使用DOMContentLoaded
  • 2.不支持的就使用Hack兼容,其原理是通过document.documentElement.doScroll('left')来判断dom树是否创建完毕。
自个儿封装
function myReady(fn){
    //兼容ie及其他
    if(document.addEventListener){
        document.addEventListener("DOMContentLoaded",fn,false)
    }else{
        IEContentLoaded(fn)
    }
    //ie模拟DOMContentLoaded
    function IEContentLoaded(fn){
        var d = window.document;
        var done = false;
        //只执行一次用户的回调函数init()
//      确保domready函数只执行一次
        var init = function(){
            if (!done){
                done = true;
                fn()
            }
        };
        //立即调用
        (function(){
            try {
                //dom为创建完成之前调用doScroll会抛出错误
                d.documentElement.doScroll('left');
            } catch(e){
                //延迟再试一次,调用函数自身
                setTimeout(arguments.callee,50);
                return;
            }
            // 没有错误表示dom创建完毕,然后立马执行用户回调
            init()
        })();
        //监听document的加载状态
        d.onreadystatechange = function(){
            // 如果用户在domready后绑定函数,立即执行
            if(d.readyState == 'complete'){
                d.onreadystatechange = null;
                init();
            }
        }
    }
}
例子代码
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>
        <script src="domReady.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript">
    myReady(function(){
            document.getElementById("h1").style.color = "red";
        })
    </script>
    <body id="box">
        <h1 id="h1">hhhhh</h1>
    </body>
</html>

番外篇
  • 大家可以通过这个地址看一下各个主流框架domready实现函数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值