给页面渲染时间加速 干掉Dom Level 0 Event


Posted in Javascript onDecember 19, 2012

现在的web应用越来越复杂,需要响应各种各样的用户触发事件,因而也就不可避免的,需要给我们的html页面上的dom元素增加事件监听函数.

我们知道给dom元素绑定事件监听函数的方法有如下3种:
1 : 页面html:

<button onclick=”test();”></button>

2: 页面html:
<button id=”btn”></button>

Javascript:
document.getElementById(“btn”).onclick = test;

3: 页面html:
<button id=”btn”></button>

Javascript:
document.getElementById(“btn”).atachEvent(“onclick”,test); //ie

这3种方法的功能效果和差异,大家都了解,在此就不在赘述了,但是这3种方法,对页面渲染的速度,资源的消耗,却是有很大不同的.

正文后面的html代码是一个demo页面,大家可以用ie浏览器打开,通过注释不同的代码段,查看页面运行效果.
可以看到第一种方式的效率是最低的,随着页面节点的增多,页面渲染时间急剧增加,在ie7下运行,大概670ms;
第二种方式明显好一些,在ie7下,大概250ms
而第三种方式则是最快的方法,也是web前端开发推荐的标准写法,在ie7下,大概188ms;
然后我们去掉事件绑定的逻辑,发现只渲染dom元素,不绑定事件的时间,仅仅125ms,可见事件绑定的时间消耗还是很大的 ,尤其是第一种方式,也就是Dom Level 0 Event,最为耗时.

另外,大家运行各段代码的时候,不妨打开任务管理器,找到浏览器对应的进程,查看代码运行时cpu的消耗以及内存的使用.
我们可以看到,Dom Level 0 Event,对cpu的消耗明显要高很多.

对内存的消耗分析:
重新打开浏览器,空白页面的内存占用量大概是37M,虚拟内存为28M,页面渲染后:
1 内存使用 54M,虚拟内存41M
2 内存使用44M,虚拟内存31M
3 内存使用44M,虚拟内存31M
可见Dom Level 0 Event对内存的消耗,也远远超出了其它方式.
为什么Dom Level 0 Event会这么消耗系统资源呢?对cpu和内存的消耗都远远超出了其它方式.我们来做一个简单分析.

为了便于分析,我们不妨修改一下我们的代码 <button onclick=”debugger;test();”></button> ,然后运行页面,在ie的script debugger里我们找到堆栈调用这一项,可以看到有一个anonymos function,这个function是从何而来的呢.原来浏览器在对Dom Level 0 Event做绑定的时候,会自动生成一个包含我们的代码的匿名函数,然后把这个匿名函数绑定到事件.类似于如下方式:

document.getElementById(“btn”).onclick = function(event){ 
test(); 
} ;

而ie浏览器又没有足够的智能,区分出众多内部功能完全一致的匿名函数并合并它们的引用,所以导致了随着dom事件绑定的越来越多,匿名函数的个数也越来越多.因为要声明数量众多的事件处理匿名函数,也就不难明白,为什么会消耗如此多的系统资源了.

随着dom元素的增多,这个资源消耗就会越来越严重.而且我们可以尝试着刷新一下页面,发现随着刷新的次数增加,页面运行越来越慢,cpu消耗也越来越多,内存也会有少量增加.可见,Dom Level 0 Event 还会带来少量的内存泄露.至于时间的延长,cpu消耗的加聚,推测是因为浏览器忙于释放众多的匿名函数所占用的资源所带来的后果.

进一步深入,由于ie浏览器是基于冒泡的事件模型,子元素的event会冒泡到父元素,所以更极致的优化,是去掉众多子元素的事件绑定,而将事件绑定到父元素,在正文后的demo中,也有这方面的尝试,可以看到不仅cpu,内存消耗最低,时间上也跟渲染干净的html页面是一样的.

所以我们在页面事件绑定中,要尽量避免Dom Level 0 Event,而且要尽可能的将事件上升.(当然也要考虑事件处理的灵活性).
demo:

<BODY> 
<ul id="list"></ul> 
<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
var $ = function(id){ 
return document.getElementById(id) 
}; 
function test(){ 
alert(1) 
} 
var ul = $("list"); 
var count = 5000; 
// ie7 
//--> 
</SCRIPT> 
<script> 
var d = new Date() 
var str = []; 
for(var i = 0;i<count;i++){ 
str.push('<li onclick="test();">'+i+'</li>') 
} 
ul.innerHTML = str.join(""); 
alert(new Date - d); 
//670 刷新时时间增加 85 
</script> 
<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
/*var d = new Date() 
var str = []; 
for(var i = 0;i<count;i++){ 
str.push('<li>'+i+'</li>') 
} 
ul.innerHTML = str.join(""); 
alert(new Date - d); */ 
//125 
//--> 
</SCRIPT> 
<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
/*var d = new Date() 
var str = []; 
for(var i = 0;i<count;i++){ 
str.push('<li>'+i+'</li>') 
} 
ul.innerHTML = str.join(""); 
var li = document.getElementsByTagName("li"); 
var l = li.length; 
for(var i=0;i<l;i++){ 
li[i].onclick = test; 
} 
li = null; 
alert(new Date - d);*/ 
//250 
//--> 
</SCRIPT> 
<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
/*var d = new Date() 
var str = []; 
for(var i = 0;i<count;i++){ 
str.push('<li>'+i+'</li>') 
} 
ul.innerHTML = str.join(""); 
var li = document.getElementsByTagName("li"); 
var l = li.length; 
for(var i=0;i<l;i++){ 
li[i].attachEvent("onclick",test); 
} 
li = null; 
alert(new Date - d);*/ 
//188 
//--> 
</SCRIPT> 
<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
/*var d = new Date() 
var str = []; 
for(var i = 0;i<count;i++){ 
str.push('<li>'+i+'</li>') 
} 
ul.innerHTML = str.join(""); 
ul.attachEvent("onclick",test); 
alert(new Date - d);*/ 
//125 
//--> 
</SCRIPT> 
</BODY>
Javascript 相关文章推荐
javascript的原生方法获取数组中的最大(最小)值
Dec 19 Javascript
jquery选择器排除某个DOM元素的方法(实例演示)
Apr 25 Javascript
js实现网页自动刷新可制作节日倒计时效果
May 27 Javascript
JavaScript跨域方法汇总
Oct 16 Javascript
jQuery+jRange实现滑动选取数值范围特效
Mar 14 Javascript
JavaScript实现鼠标滑过处生成气泡的方法
May 16 Javascript
seajs加载jquery时提示$ is not a function该怎么解决
Oct 23 Javascript
Bootstrap弹出带合法性检查的登录框实例代码【推荐】
Jun 23 Javascript
vue判断input输入内容全是空格的方法
Mar 02 Javascript
Vue filter介绍及详细使用
Apr 04 Javascript
vue中axios实现数据交互与跨域问题
May 12 Javascript
微信小程序按顺序同步执行的两种方式
Dec 20 Javascript
img onload事件绑定各浏览器均可执行
Dec 19 #Javascript
JavaScript实现快速排序(自已编写)
Dec 19 #Javascript
js 使用form表单select类实现级联菜单效果
Dec 19 #Javascript
JS限制上传图片大小不使用控件在本地实现
Dec 19 #Javascript
JS上传图片前的限制包括(jpg jpg gif及大小高宽)等
Dec 19 #Javascript
js限制文本框输入长度两种限制方式(长度、字节数)
Dec 19 #Javascript
ajax java 实现自动完成功能
Dec 19 #Javascript
You might like
MOTOROLA 摩托罗拉 MODEL 66-XI五灯中波收音机
2021/03/02 无线电
php jq jquery getJSON跨域提交数据完整版
2013/09/13 PHP
php发送与接收流文件的方法
2015/02/11 PHP
PHP学习笔记(三):数据类型转换与常量介绍
2015/04/17 PHP
简单解决微信文章图片防盗链问题
2016/12/17 PHP
如何判断php mysqli扩展类是否开启
2016/12/24 PHP
laravel5.6框架操作数据curd写法(查询构建器)实例分析
2020/01/26 PHP
javascript计时器事件使用详解
2014/01/07 Javascript
jquery实现效果比较好的table选中行颜色
2014/03/25 Javascript
javaScript中两个等于号和三个等于号之间的区别介绍
2014/06/27 Javascript
jQuery EasyUI 菜单与按钮之创建简单的菜单和链接按钮
2015/11/18 Javascript
简单了解Backbone.js的Model模型以及View视图的源码
2016/02/14 Javascript
JavaScript 数组some()和filter()的用法及区别
2016/05/20 Javascript
JS仿JQuery选择器功能
2017/03/08 Javascript
详解Vue如何支持JSX语法
2017/11/10 Javascript
使用Vue完成一个简单的todolist的方法
2017/12/01 Javascript
微信小程序实现的涂鸦功能示例【附源码下载】
2018/01/12 Javascript
详解layui中的树形关于取值传值问题
2018/01/16 Javascript
vue轮播图插件vue-concise-slider的使用
2018/03/13 Javascript
Vue2.5学习笔记之如何在项目中使用和配置Vue
2018/09/26 Javascript
Vue组件系列开发之模态框
2019/04/18 Javascript
JS实现使用POST方式发送请求
2019/08/30 Javascript
Python实现的rsa加密算法详解
2018/01/24 Python
django如何实现视图重定向
2019/07/24 Python
python图形开发GUI库pyqt5的详细使用方法及各控件的属性与方法
2020/02/14 Python
python实现126邮箱发送邮件
2020/05/20 Python
Omio俄罗斯:一次搜索公共汽车、火车和飞机的机票
2018/11/17 全球购物
FORZIERI福喜利中国官网:奢侈品购物梦工厂
2019/05/03 全球购物
德国帽子专家:Hutshopping
2019/11/03 全球购物
KEEN美国官网:美国人气户外休闲鞋品牌
2021/03/09 全球购物
先进工作者获奖感言
2014/02/08 职场文书
幼儿园教师师德师风演讲稿:我自豪我是一名幼师
2014/09/10 职场文书
2014年教师节座谈会发言稿
2014/09/10 职场文书
九一八事变演讲稿范文
2014/09/14 职场文书
Pytorch中Softmax和LogSoftmax的使用详解
2021/06/05 Python
Python socket如何解析HTTP请求内容
2022/02/12 Python