等待HTML DOM的加载

 处理HTML DOM文档存在的一个难题是,JavaScript可以在DOM完全加载之前执行,这会给你的代码引发不少的潜在问题。浏览器的渲染和操作顺序大致如以下列表:

l    HTML解析完毕。
l    外部脚本和样式表加载完毕。
l    脚本在文档内解析并执行。
l    HTML DOM完全构造起来。
l    图片和外部内容加载。
l    网页完成加载。

在网页头部并且从外部文件加载的脚本会在HTML真正构造之前执行。如前所述,这是个至关重要的问题,因为这两处执行的脚本并不能访问还不存在的DOM。幸好,我们还有若干的补救办法。

1、 等待整个页面的加载

目前,最常用的技术是完全等待整个页面加载完毕才执行DOM操作。这种技术只需利用window对象的load事件来绑定一个函数,页面加载完毕即可触发。我们将会在第6章更详细地讨论事件。代码清单5-10展示了一个页面完成加载后执行DOM相关代码的例子。

代码清单5-10 使用addEvent函数为window.onload属性绑定回调函数

// 直到页面加载完毕

// (使用的addEvent, 下一章会有阐述)

addEvent(window, "load", function() {
    // 执行HTML DOM操作
    next( id("everywhere") ).style.background = 'blue';
});

最简单的操作却是最慢的。在加载过程的顺序列表中,你会注意到页面的加载完毕与否完全被最后一步所掌控。这就是说,如果你页面有很多的图片、视频等,用户可能得等上一段时间JavaScript才执行。

2、 等待大部分DOM的加载

第二种技术相当绕弯子,所以并不是十分推荐使用。如果你还记得,前面说过行内的脚本在DOM构造后就可立即执行。这是准真理。只有在DOM构造后,执行到该位置上脚本才真正执行。这意味着在你在页面中途嵌入的行内脚本只能访问该位置之前的DOM。所以,在页面最后元素之前嵌入脚本,你就可以在DOM中访问这个元素之前全部的元素,成为一条模拟DOM加载的伪路子。该方法典型的实现如代码清单5-11所示。

代码清单5-11 依靠在HTML DOM最后插入一个

    <h1>Testing DOM Loading</h1>
    <!-- 这里是大量的HTML -->

在这个例子中,你必须把行内脚本作为DOM的最后一个元素,以便它最后一个被解析和执行。它唯一执行的是初始化函数,该函数应该包含你需要操作的DOM的相关代码。这个解决方案的最大问题在于混乱:你为HTML增添无关标记的理由仅仅是检查DOM是否已经执行。该技术通常被认为是不合理的,因为你为页面增加额外的代码的目的只是检查加载状态而已。

3、 判断DOM何时加载完毕

最后一种技术可用以监听DOM加载状态,可能是最复杂的(从实现角度来看),但也是最有效的。在该技术中,你既能像绑定window加载事件那般简单,又能获得行内脚本技术那样的速度。

这项技术在不堵塞浏览器加载的情况下尽可能快地检查HTML DOM文档是否已经加载了执行所必须的属性。以下是检查HTML DOM是否可用的几个要点:

(1) document:你需要知道DOM文档是否已经加载。若能足够快地检查,运气好的话你会看到undefined。
(2) document.getElementsByTagName和documents.getElementById:频繁使用docum- ent.getElementsByTagName和document.getElementById函数检查文档,当存在这些函数则表明已完成加载。
(3) document.body:作为额外补充,检查

使用这些检查就足够判断DOM是否可用了(“足够”在此表示可能会有一定毫秒级的时间差)。这个方法几乎没有瑕疵。单独使用前述检查,脚本应该可以在现代浏览器中运行得相对良好。但是,最近Firefox实现了缓存改进,使得window 加载事件实际上可以在脚本能检查到DOM是否可用之前触发。为了能发挥这个优势,我同时为window加载事件附加检查,以期能获得更快的执行速度。

最后,domReady函数集合了所有需要在DOM可用时就执行的函数的引用。一旦DOM被认为是可用的,就调用这些引用并按顺序一一执行。代码清单5-12展示了一个监听DOM何时加载完毕的函数。

代码清单5-12 监听DOM是否可用的函数

function domReady( f ) {

  // 假如 DOM 已经加载,马上执行函数
  if ( domReady.done ) return f();

  // 假如我们已经增加了一个函数
  if ( domReady.timer ) {

    // 把它加入待执行函数清单中
    domReady.ready.push( f );
  } else {

    // 为页面加载完毕绑定一个事件,
    // 以防它最先完成。使用addEvent(该函数见下一章)。
    addEvent( window, "load", isDOMReady );

    // 初始化待执行函数的数组
    domReady.ready = [ f ];

   // 尽可能快地检查DOM是否已可用
    domReady.timer = setInterval( isDOMReady, 13 );
  }
}

// 检查DOM是否已可操作

function isDOMReady() {

  // 如果我们能判断出DOM已可用,忽略
  if ( domReady.done ) return false;

  // 检查若干函数和元素是否可用
  if ( document && document.getElementsByTagName &&
       document.getElementById && document.body )
  {

    // 如果可用,我们可以停止检查
    clearInterval( domReady.timer );
    domReady.timer = null;

    // 执行所有正等待的函数
    for ( var i = 0; i < domReady.ready.length; i++ )

      domReady.ready[i]();
    // 记录我们在此已经完成
    domReady.ready = null;
    domReady.done = true;
  }
}

现在该来看看这在HTML文档中是如何执行的。domReady函数应该按addEvent函数(第6章将讨论)的方式使用,文档可操作时即绑定你需要执行的函数。代码清单5-13展示了如何使用domReady函数来监听DOM是否可用。在这个例子中,假设已经将domReady函数写到一个名为domready.js的外部文件中。

代码清单5-13 使用domReady函数来确定何时DOM可操作和修改

    <title>Testing DOM Loading</title>
  <h1>Testing DOM Loading</h1>

  <!--这里是大量的HTML -->

现在你已经掌握若干定位一般XML DOM文档与如何补救HTML DOM文档加载难题的方法,另一个问题也该摆上台面了:还有更好的方法来查找HTML文档中的元素吗?当然,答案是十分肯定的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值