海淀网站制作,进行网站建设的上市公司,吴江市建设局网站,建设工程合同管理考试试题及答案1、浏览器渲染引擎的HTML解析流程 何谓“渲染”#xff0c;其实就是浏览器把请求到的HTML内容显示出来的过程。渲染引擎首先通过网络获得所请求文档的内容#xff0c;通常以8K分块的方式完成。下面是渲染引擎在取得内容之后的基本流程#xff1a; 1#xff0c;解析html以构…1、浏览器渲染引擎的HTML解析流程 何谓“渲染”其实就是浏览器把请求到的HTML内容显示出来的过程。渲染引擎首先通过网络获得所请求文档的内容通常以8K分块的方式完成。下面是渲染引擎在取得内容之后的基本流程 1解析html以构建dom树构建DOM节点渲染引擎开始解析html并将标签转化为内容树中的dom节点。 2构建render树解析样式信息解析外部CSS文件及style标签中的样式信息。Render树由一些包含有各种属性的矩形组成它们将被按照正确的顺序显示到屏幕上。 3布局render树布局DOM节点执行布局过程它将确定每个节点在屏幕上的确切坐标。 4绘制render树绘制DOM节点Render树构建好了之后将会再下一步就是绘制即遍历render树并使用UI后端层绘制每个节点。 以上就是HTML渲染的基本流程但这并不包含解析过程中浏览器加载外部资源如图片、脚本、iframe等的过程。说白了上面的四步仅仅是HTML结构的渲染流程而外部资源的加载在HTML结构的渲染流程中贯穿始终即便绘制DOM节点已经完成外部资源依然可能正在加载中或尚未加载。 2、window.onload 了解了浏览器渲染引擎的HTML解析流程我们就回到domReady。前文提到了那个蛋疼的TypeError是由于在DOM树构建完成之前对节点进行了操作而通常的解决的办法就是让js在window.onload的回调里执行也就是说在文档所有的解析渲染、资源加载完成之前不让js脚本执行这样一来就妥妥地避免了因js操作先于DOM树创建而带来的bug 1 Window.onload function(){
2 //doSomething
3 } 这样的解决办法应该是初学原生js时很多人最常用的解决办法看起来也的确没什么问题。如果文档外部资源不多的时候也没什么问题但我们来做一个假设。假设一个页面上有100张远程图片我需要让js做到在点击每张图片时alert出图片的src属性又该怎么做 是不是已经发现点小问题了按照第二部分内容对浏览器解析渲染HTML流程的介绍DOM树很快就构建完毕了而100张图片还在缓慢地加载。而要想执行alert出图片src属性的js则需要等到100张图片全部加载完成后才能执行。而在这期间页面元素不会响应你的任何操作就好像“死”了一样。如果是在实际项目中用户很可能不会等到你页面所有东东加载完以后才去操作在面对一个不会对自己的操作做任何响应的页面唯一比较解气的方式就是——果断关掉~然后……就没有了然后。 所以在实际应用中我们经常会遇到这样的场景让页面加载后去做一些事情绑定事件、DOM操作某些结点等。使用window.onload对于很多实际的应用而言有点太“迟”了比较影响用户体验。那有没有更好的方法解决这个问题比如提前到只要DOM树创建完成之后就可以进行如上操作呢答案当然是有的DOMContentLoaded事件。 3、DOMContentLoaded 说这个之前必须要提一下jQuery中的domReady机制。很多时候在使用jq也会出现最前面出现的那个TypeError解决办法就是把js放到jQuery的ready回调里 1 $(document).ready(function(){...}); 或者 1 $(function(){...}); 这样一来错误妥妥地没了。然后对比因果关系大概得出一个结论jQuery的ready回调应该跟window.onload的效果原理是一样的。恩应该是这样。那我们就先来看一看jQuery1.11.1的ready回调是如何实现的 1 jQuery.fn.ready function( fn ) {2 // Add the callback3 jQuery.ready.promise().done( fn );4 return this;5 };6 jQuery.ready.promise function( obj ) {7 if ( !readyList ) {8 readyList jQuery.Deferred();9 if ( document.readyState complete ) {
10 setTimeout( jQuery.ready );
11 } else if ( document.addEventListener ) {
12 document.addEventListener( DOMContentLoaded, completed, false );
13 window.addEventListener( load, completed, false );
14 } else {
15 document.attachEvent( onreadystatechange, completed );
16 window.attachEvent( onload, completed );
17 var top false;
18 try {
19 top window.frameElement null document.documentElement;
20 } catch(e) {}
21 if ( top top.doScroll ) {
22 (function doScrollCheck() {
23 if ( !jQuery.isReady ) {
24 try {
25 // Use the trick by Diego Perini
26 top.doScroll(left);
27 } catch(e) {
28 return setTimeout( doScrollCheck, 50 );
29 }
30 detach();
31 jQuery.ready();
32 }
33 })();
34 }
35 }
36 }
37 return readyList.promise( obj );
38 }; 看起来比想象中的window.onload要复杂呵。Jq的源码中出现了DOMContentLoaded、readyState、onreadystatechange这些跟domReady有什么关系 我们还是先从DOMContentLoaded说起吧。就如前面所述很多时候我们会把js逻辑写在window.onload回调中以防DOM树还没有建完就开始对节点进行操作从而导致错误而对于很多实际应用来说越早介入对DOM的干涉就越好比如进行特征侦测、事件绑定、DOM操作神马的。domReady还可以满足用户提前绑定事件的需求因为有些情况下页面的图片等外部资源过多window.onload迟迟不能触发这时若还没有绑定事件用户点任何的按钮都没反应链接除外会直接影响体验。 为了解决window.onload的短板FF中便增加了一个DOMContentLoaded方法与onload相比DOMContentLoaded方法触发的时间更早它是在页面的DOM树创建完成后也就是HTML解析第一步完成即触发而无需等待其他资源的加载。Webkit引擎从版本525Webkit nightly 1/2008:525开始也引入了该事件Opera中也包含该方法。到目前为止NB的IE仍然没有要添加的意思。虽然IE下没有但解决办法总是有的。于是对于那些忙前忙后的兼容小达人和死不悔改的顽固派也就有了两套策略 1支持DOMContentLoaded事件的就使用DOMContentLoaded事件 2不支持的就用来自Diego Perini发现的著名Hack兼容。兼容原理大概就是通过IE中的document.documentElement.doScroll(‘left’)来判断DOM树是否创建完毕。 Blabla了这么多来看个IE模拟DOMContentLoaded例子吧。这个例子就来自上面发现IE下doScroll Hackd的作者细看也就是简化版的jQuery.ready回调的IE处理逻辑。 1 function IEContentLoaded (w, fn) {2 var d w.document, done false,3 // 只执行一次用户的回调函数init()4 init function () {5 if (!done) {6 done true;7 fn();8 }9 };
10 (function () {
11 try {
12 // DOM树未创建完之前调用doScroll会抛出错误
13 d.documentElement.doScroll(left);
14 } catch (e) {
15 //延迟再试一次~
16 setTimeout(arguments.callee, 50);
17 return;
18 }
19 // 没有错误就表示DOM树创建完毕然后立马执行用户回调
20 init();
21 })();
22 //监听document的加载状态
23 d.onreadystatechange function() {
24 // 如果用户是在domReady之后绑定的函数就立马执行
25 if (d.readyState complete) {
26 d.onreadystatechange null;
27 init();
28 }
29 };
30 } 而对于高大上的chrome、ff等高级浏览器来说对DOMContentLoaded事件的处理就相对来说小case了按照标准的事件绑定方式就可以处理 1 if ( document.addEventListener ) {
2 document.addEventListener( DOMContentLoaded, completed, false );
3 } 五、实例 看到这想必大家已经对DOMContentLoaded已经有了新的认识onload保险丝也该适时换成智能电门啦~接下来就来个鲜活的例子来让大家更清晰的做下对比。 首先页面上有一组图片 1 ul
2 liimg srcimg/01.jpg //li
3 liimg srcimg/02.jpg //li
4 liimg srcimg/03.jpg //li
5 liimg srcimg/04.jpg //li
6 liimg srcimg/05.jpg //li
7 /ul 页面的js处理逻辑 1 script2 var d document;3 var msgBox d.getElementById(showMsg);4 var imgs d.getElementsByTagName(img);5 var time1 null,time2 null;6 if(d.addEventListener){7 d.addEventListener(DOMContentLoaded,domReady,false);8 }else{9 IEContentLoaded(domReady);
10 }
11 function domReady(){
12 msgBox.innerHTML dom已加载br;
13 time1 new Date().getTime();
14 msgBox.innerHTML 时间戳 time1 br;
15 }
16
17 //兼容IE的domReady
18 function IEContentLoaded(fn){
19 var done false,
20 init function(){
21 if(!done){
22 done true;
23 fn();
24 }
25 };
26 (function(){
27 try {
28 d.documentElement.doScroll(left);
29 }catch(e){
30 setTimeout(arguments.callee,50);
31 return;
32 }
33 init();
34 })();
35 d.onreadystatechange function(){
36 msgBox.innerHTML 加载状态 d.readyState br;
37 if(d.readyState complete){
38 d.onreadystatechange null;
39 }
40 }
41 }
42 window.onload function(){
43 msgBox.innerHTML onload已加载br;
44 time2 new Date().getTime();
45 msgBox.innerHTML 时间戳 time2 br;
46 msgBox.innerHTML domReady比onload快 (time2 - time1) msbr;
47 }
48 /script 相信js脚本不用做过多解释在前面都已做过详细分析我们直接来看运行结果 很容易就能看出DOMContentLoaded执行5238ms之后才执行的onload。这只是一个DEMO的差距而如果是更大型的应用可能这个时间差距会更大。 转载于:https://www.cnblogs.com/wang985850293/p/5231400.html