重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
载入脚本或者脚本在执行了一些较多的页面载入完成的事件 可能由于js文件未完全载入导致假死
创新互联专注为客户提供全方位的互联网综合服务,包含不限于成都网站制作、成都网站建设、外贸营销网站建设、汶上网络推广、小程序定制开发、汶上网络营销、汶上企业策划、汶上品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;创新互联为所有大学生创业者提供汶上建站搭建服务,24小时服务热线:18980820575,官方网址:www.cdcxhl.com
刷新之后可能文件载入完成操作就正常了
泽元的框架太大了 压缩之后还100多k
建议使用我的框架
第二关于弹出层的问题 我也自己写了一个(当然参考了泽元的代码 修正泽元的bug 具体bug就不指出了) 当然ui是用的泽元的 我发给你代码
图片相信你自己有就不用我给你了吧
注意:上面的框架不要和下面的弹出层放一起 我没有做检查 有些函数可能在我的框架里已经有了 可能导致冲突报错 等以后检查了 再到我的空间来看
/*xs.Dialog.js 作者:肖毅 转载请保留这段申明 */
var PicPath = "/MX_Admin/Images/";
var isIE = navigator.userAgent.toLowerCase().indexOf("msie") != -1;
var isGecko = navigator.userAgent.toLowerCase().indexOf("gecko") != -1;
//获取当前窗口最顶级的window对象
function $TW() {
var pw = window;
while(pw!=pw.parent){
pw = pw.parent;
}
return pw;
}
//阻止一切事件执行,包括浏览器默认的事件
function stopEvent(event){
if(!event){
return;
}
if(isGecko){
event.preventDefault();
event.stopPropagation();
}
event.cancelBubble = true
event.returnValue = false;
}
function Dialog(sID) {
this.ID = sID;
this.Width = 400;
this.Height = 200;
this.Title = "系统提示-网页对话框";
this.URL = null;
this.Alert = "";
this.DialogArguments = {};
this.Message = null;
this.MessageTitle = null;
this.ShowMessageRow = false;
this.ShowButtonRow = true;
this.Icon = null;
this.Mask=null;
}
Dialog._Array = [];
Dialog.prototype.show = function(){
var pw = $TW();
var mw = Math.max(pw.document.body.clientWidth,pw.document.body.scrollWidth);
var mh = Math.max(pw.document.body.clientHeight,pw.document.body.scrollHeight);
this.DialogArguments._DialogInstance = this;
this.DialogArguments.ID = this.ID;
//UI创建
var arr = [];
arr.push("table style='-moz-user-select:none;' oncontextmenu='stopEvent(event);' onselectstart='stopEvent(event);' width='100%' height='100%' border='0' cellspacing='0' cellpadding='0'");
arr.push("tr id='_DialogTitle_"+this.ID+"' style='backgound-color:;'");
arr.push("td width='13' height='33' align='center' style='background:url("+PicPath+"dialog_title.png); background-repeat:no-repeat;'");
arr.push("div style='width:13px;'/div/td");
arr.push("td height='33' style='background:url("+PicPath+"dialog_ct.png); background-repeat:repeat-x;'");
arr.push("div style='float:left;font-weight:bold; color:#FFFFFF; padding:9px 0 0 4px; font-size:12px;'");
arr.push("img src='"+PicPath+"icon_dialog.gif' align='absmiddle' "+this.Title+"/div");
arr.push("div style='position: relative;cursor:pointer; float:right; margin:5px 0 0; _margin:4px 0 0;height:17px; width:28px; background:url("+PicPath+"dialog_closebtn.gif);' onMouseOver=\"this.style.backgroundImage='url("+PicPath+"dialog_closebtn_over.gif)'\" onMouseOut=\"this.style.backgroundImage='url("+PicPath+"dialog_closebtn.gif)'\" id='_DialogClose_"+this.ID+"' drag='false' onClick=\"Dialog.getInstance('"+this.ID+"').CancelButton.onclick.apply(Dialog.getInstance('"+this.ID+"').CancelButton,[]);\"/div/td");
arr.push("td width='13' height='33' style='background:url("+PicPath+"dialog_rt.png); background-repeat:no-repeat;'");
arr.push("div style='width:13px;'/div/td/tr");
arr.push("tr drag='false'td width='13' style='background:url("+PicPath+"dialog_mlm.png); background-repeat:no-repeat;'/td");
arr.push("td align='center' valign='top'");
arr.push("table width='100%' height='100%' border='0' cellpadding='0' cellspacing='0' bgcolor='#FFFFFF'");
arr.push("tr id='_MessageRow_"+this.ID+"' style='display:none;'");
arr.push("td height='50' valign='top'table id='_MessageTable_"+this.ID+"' width='100%' border='0' cellspacing='0' cellpadding='8' style='background:#EAECE9 url("+PicPath+"dialog_bg.jpg) no-repeat right top;'");
arr.push("trtd width='40' height='50' align='right'img id='_MessageIcon_"+this.ID+"' src='"+PicPath+"window.gif' width='32' height='32'/td");
arr.push("td align='left' style='line-height:16px; padding-left:6px;'");
arr.push("h5 id='_MessageTitle_"+this.ID+"' /h5");
arr.push("div id='_Message_"+this.ID+"' /div/td");
arr.push("/tr/table/td/tr");
arr.push("trtd align='center' valign='top'");
arr.push("valign='top'");
arr.push("iframe src='"+this.URL+"' id='_DialogFrame_"+this.ID+"' allowTransparency='true' width='100%' height='100%' frameborder='0' style='background-color: #transparent;border:none;overflow-x:hidden;'/iframe");
arr.push("/td/tr");
arr.push("tr drag='false' id='_ButtonRow_"+this.ID+"'td height='36'");
arr.push("div id='_DialogButtons_"+this.ID+"' style='text-align:right; border-top:#dadee5 1px solid; padding:8px 20px; background-color:#f6f6f6;'");
arr.push("input id='_ButtonOK_"+this.ID+"' type='button' value='确 定'");
arr.push("input id='_ButtonCancel_"+this.ID+"' type='button' onclick=\"Dialog.getInstance('"+this.ID+"').close();\" value='取 消'");
arr.push("/div/td/tr");
arr.push("/table/tdtd width='13' style='background:url("+PicPath+"dialog_mrm.png); background-repeat:no-repeat;'/td/tr");
arr.push("trtd width='13' height='13' style='background:url("+PicPath+"dialog_lb.png); background-repeat:no-repeat;'/td");
arr.push("td style='background-image:url("+PicPath+"dialog_cb.png); background-repeat:repeat-x;'/td");
arr.push("td width='13' height='13' style='background-image:url("+PicPath+"dialog_rb.png); background-repeat:no-repeat;'/td");
arr.push("/tr/table");
var Mask = pw.$("_DialogMask");
if(!Mask) {
Mask = pw.document.createElement("div");
Mask.id = "_DialogMask";
Mask.style.position = "absolute";
Mask.style.zIndex = "5000";
Mask.style.width = mw;
Mask.style.height = mh;
Mask.style.top = "0px";
Mask.style.left = "0px";
Mask.style.background = "#33393C";
Mask.style.filter = "alpha(opacity=10)";
Mask.style.opacity = "0.10";
Mask.style.display = "none";
pw.document.body.appendChild(Mask);
}
//创建弹出窗口
var div = pw.document.createElement("div");
div.id = "_Dialog_"+this.ID;
div.style.position = "absolute";
div.style.background=""; //必须设置为空 防止在某些主题下产生白色边框
div.style.zIndex = "10000";
div.style.width = this.Width + "px";
div.style.height = this.Height + "px";
div.style.top = parseInt(pw.document.body.scrollTop+pw.document.body.clientHeight/2 - this.Height/2) + "px";
div.style.left = parseInt(pw.document.body.clientWidth/2 - this.Width/2) + "px";
div.style.display = "none";
pw.document.body.appendChild(div);
this.DialogDiv = div;
div.innerHTML = arr.join('\n');
pw.$("_DialogFrame_"+this.ID).DialogInstance = this;
pw.Drag.init(pw.$("_DialogTitle_"+this.ID),pw.$("_Dialog_"+this.ID));//注册拖拽方法
this.OKButton = pw.$("_ButtonOK_"+this.ID);
this.CancelButton = pw.$("_ButtonCancel_"+this.ID);
//显示标题图片
if(this.ShowMessageRow){
pw.$("_MessageRow_"+this.ID).style.display = "";
if(this.MessageTitle){
pw.$("_MessageTitle_"+this.ID).innerHTML = this.MessageTitle;
}
if(this.Message){
pw.$("_Message_"+this.ID).innerHTML = this.Message;
}
}
//显示按钮栏
if(!this.ShowButtonRow){
pw.$("_ButtonRow_"+this.ID).style.display = "none";
}
if(this.CancelEvent){
this.CancelButton.onclick = this.CancelEvent;
}
if(this.OKEvent){
this.OKButton.onclick = this.OKEvent;
this.returnValue = true;
}
if(this.URL == "") {
var win = pw.$("_DialogFrame_"+this.ID).contentWindow;
var doc = win.document;
doc.open();
doc.write("body oncontextmenu='return false;'/body") ;
var arr = [];
arr.push("table height='100%' border='0' align='left' cellpadding='10' cellspacing='0'");
arr.push("trtd align='right'img id='Icon' src='"+this.Icon+"' width='34' height='34' align='absmiddle'/td");
arr.push("td align='left' id='Message' style='font-size:9pt'"+this.Alert+"/td/tr/table");
var div = doc.createElement("div");
div.innerHTML = arr.join('');
doc.body.appendChild(div);
doc.close();
}
this.Mask = "_DialogMask";
pw.$("_Dialog_"+this.ID).style.display = "";
if(pw.$("_DialogMask").style.display == "none") {
pw.$("_DialogMask").style.display = "";
var k = 1,timer=null;
timer=setInterval(function(){
k = k + 1;
if(k5) {
Mask.style.filter = "alpha(opacity="+k*10+")";
Mask.style.opacity = ""+k/10+"";
}
},10);
} else {
clearInterval(timer);
}
pw.$("_Dialog_"+this.ID).focus();
pw.$("_DialogFrame_"+this.ID).focus();
if(this.ShowButtonRow){
this.OKButton.focus();
}
//放入队列中
pw.Dialog._Array.push(this.ID);
if(pw.Dialog._Array.length1) {
for(i=0;ipw.Dialog._Array.length-1;i++) {
pw.Dialog.getInstance(pw.Dialog._Array[i]).DialogDiv.style.zIndex=4000+i;
}
}
}
Dialog.prototype.close = function(){
var pw = $TW();
pw.Dialog._Array.remove(this.ID);
if(pw.Dialog._Array.length==0) {
pw.$("_DialogMask").style.display = "none";
pw.document.body.removeChild(pw.$("_DialogMask"));
} else {
pw.Dialog.getInstance(pw.Dialog._Array[pw.Dialog._Array.length-1]).DialogDiv.style.zIndex=10000;
pw.Drag.init(pw.$("_DialogTitle_"+pw.Dialog._Array[pw.Dialog._Array.length-1]),pw.$("_Dialog_"+pw.Dialog._Array[pw.Dialog._Array.length-1]));
}
pw.$("_Dialog_"+this.ID).style.display = "none";
pw.document.body.removeChild(pw.$("_Dialog_"+this.ID));
}
Dialog.blink = function () {
var pw = $TW();
if(pw.Dialog._Array.length0) {
var target = pw.Dialog.getInstance(pw.Dialog._Array[pw.Dialog._Array.length-1]);
var sl = parseInt(target.DialogDiv.style.left);
var st = parseInt(target.DialogDiv.style.top);
var sr = sl + target.Width;
var sb = st + target.Height;
if(pw.event.clientXsl || pw.event.clientYst || pw.event.clientXsr || pw.event.clientYsb) {
pw.$("_DialogTitle_"+target.ID).childNodes[1].style.filter = "alpha(opacity=20)";
pw.$("_DialogTitle_"+target.ID).style.opacity = "0.20";
setTimeout(function() {
pw.$("_DialogTitle_"+target.ID).childNodes[1].style.filter = "";
pw.$("_DialogTitle_"+target.ID).style.opacity = "1.00";
}
,50);
}
} else {
return;
}
}
Dialog.getInstance = function(id){
var pw = $TW();
var f = pw.$("_DialogFrame_"+id);
if(!f){
return null;
}
return f.DialogInstance;
}
Dialog.Alert = function (str) {
var pw = $TW();
var diag = new Dialog("Alert");
diag.Width = 400;
diag.Height = 224;
diag.Title = "系统提示-网页对话框";
diag.URL = "";
diag.Alert = str;
diag.Icon = PicPath+"icon_alert.gif"
diag.ShowMessageRow = false;
diag.show();
Dialog.getInstance("Alert").CancelButton.value = "确 定";
Dialog.getInstance("Alert").OKButton.style.display = "none";
Dialog.getInstance("Alert").CancelButton.focus();
}
Dialog.Confirm = function (str,func1,func2) {
var pw = $TW();
var diag = new Dialog("Confirm");
diag.Width = 400;
diag.Height = 224;
diag.Title = "系统提示-网页对话框";
diag.URL = "";
diag.Alert = str;
diag.Icon = PicPath+"icon_query.gif";
diag.ShowMessageRow = false;
diag.CancelEvent = function(){
diag.close();
if(func2) {
func2();
}
};
diag.OKEvent = function(){
diag.close();
if(func1) {
func1();
}
};
diag.show();
}
Dialog.setPosition = function() {
var pw = $TW();
var DialogArr=pw.Dialog._Array;
if(DialogArr==null||DialogArr.length==0)return;
for(i=0;iDialogArr.length;i++){
pw.$("_DialogFrame_"+DialogArr[i]).DialogInstance.setPosition();
}
}
Dialog.prototype.setPosition = function() {
var pw = $TW();
var mw = Math.max(pw.document.body.clientWidth,pw.document.body.scrollWidth);
var mh = Math.max(pw.document.body.clientHeight,pw.document.body.scrollHeight);
this.DialogDiv.style.top = parseInt(pw.document.body.scrollTop+pw.document.body.clientHeight/2 - this.Height/2) + "px";
this.DialogDiv.style.left = parseInt(pw.document.body.clientWidth/2 - this.Width/2) + "px";
pw.$(this.Mask).style.width= mw + "px";
pw.$(this.Mask).style.height= mh + "px";
}
Dialog.onKeyUp = function(event){
var pw = $TW();
if(window.event.keyCode==9){
if(pw.Dialog._Array.length0){
stopEvent(window.event);
}
}
if(window.event.keyCode==27){
if(pw.Dialog._Array.length0){
var diag = pw.Dialog.getInstance(pw.Dialog._Array[pw.Dialog._Array.length-1]);
diag.CancelButton.onclick.apply(diag.CancelButton,[]);
}
}
if(window.event.ctrlKey window.event.keyCode == 65) {
stopEvent(pw.event);
}
}
var Drag = {
target:null,
init:function(handle,dragMain) {
Drag.target = handle;
Drag.target.style.cursor="move";
handle.root = dragMain;
handle.onmousedown = Drag.start;
},
start:function() {
var handle = Drag.target;
Drag.mouseX = window.event.clientX;
Drag.mouseY = window.event.clientY;
Drag.flag = true;
document.onmousemove = Drag.move;
document.onmouseup = Drag.end;
},
move:function() {
if(Drag.flag) {
if(window.event.button==1 | window.event.which==1) {
var handle = Drag.target;
var mouseX = window.event.clientX;
var mouseY = window.event.clientY;
var top = parseInt(handle.root.style.top);
var left = parseInt(handle.root.style.left);
var cl = left + (mouseX - Drag.mouseX);
var ct = top + (mouseY - Drag.mouseY);
handle.root.style.left = cl + "px";
handle.root.style.top = ct + "px";
Drag.mouseX = mouseX;
Drag.mouseY = mouseY;
}
}
},
end:function() {
document.onmousemove = null;
document.onmouseup = null;
Drag.flag = false;
}
};
if(isIE){
document.attachEvent("onkeydown",Dialog.onKeyUp);
$TW().document.attachEvent("onclick",Dialog.blink);
window.attachEvent('onresize',Dialog.setPosition);
}else{
document.addEventListener("keydown",Dialog.onKeyUp,false);
$TW().document.addEventListener("click",Dialog.blink,false);
window.addEventListener('resize',Dialog.setPosition,false);
}
function alert(str) {
Dialog.Alert(str);
}
function confirm(str,func1,func2) {
Dialog.Confirm(str,func1,func2);
}
为什么页面会卡顿呢,以60Hz为例,即一秒钟的动画就是由60张静态图片连在一起。60fps是动画播放比较理想、比较基础的要求,windows系统有个刷新频率也是这个意思。60fps就要求一帧的时间为1s/60=16.67ms。浏览器显示页面的时候,要处理js逻辑,还要做渲染,每个执行片段的时间不能超过16.67ms。实际上,浏览器内核自身支撑体系运行也需要消耗一些时间,所以留给我们的时间差不多只有10ms。并且在处理js计算时,浏览器不会响应用户的操作,所以就造成了页面“假死”。
Web Work,就是为JavaScript创造多线程环境,允许主线程创建Web Worker线程,将一些任务分配给后台运行。在主线程运行的同事,Work线程在后台运行,两者互不干扰。等到Work线程完成计算任务再把结果返回给主线程。这样的好处是,一些密集或者高延迟的计算任务,被Work线程给分担了,这样主线程就会很流程。
Worker线程一旦创建成功,就会始终运行,不会被主线程上的活动打断取消。这样有利于随时响应主线程的通信。但是,这也造成了Worker比较耗费资源,不应该过度使用,所以一旦使用完毕,就应该关闭。
1.同源限制:分配给Worker线程运行的脚本文件,必须与主线程的脚本文件同源。
2.DOM限制:Work线程所在的全局对象和主线程不一样,所以无法读取主线程所在网页的DOM对象,也无法使用document,window,parent这些对象。但是可以使用navigator和location。
3.通信联系:Worker线程和主线程不在同一个上下文环境,他们不能直接通信,必须通过消息完成。
4.脚本限制:Worker线程不能执行alert和confirm方法,但是可以使用XMLHttpRequest对象发出的AJAX请求。
5.文件限制:Work线程不能读取本地文件,它所加载的脚本必须来自网络。
Event Loop 是一个很重要的概念,指的是计算机系统的一种运行机制。
JavaScript语言就采用这种机制,来解决单线程运行带来的一些问题。
Event Loop
本文参考C. Aaron Cois的《Understanding The Node.js Event Loop》,解释什么是Event Loop,以及它与JavaScript语言的单线程模型有何关系。
想要理解Event Loop,就要从程序的运行模式讲起。运行以后的程序叫做"进程"(process),一般情况下,一个进程一次只能执行一个任务。
如果有很多任务需要执行,不外乎三种解决方法。
(1)排队。因为一个进程一次只能执行一个任务,只好等前面的任务执行完了,再执行后面的任务。
(2)新建进程。使用fork命令,为每个任务新建一个进程。
(3)新建线程。因为进程太耗费资源,所以如今的程序往往允许一个进程包含多个线程,由线程去完成任务。(进程和线程的详细解释,请看这里。)
以JavaScript语言为例,它是一种单线程语言,所有任务都在一个线程上完成,即采用上面的第一种方法。一旦遇到大量任务或者遇到一个耗时的任务,网页就会出现"假死",因为JavaScript停不下来,也就无法响应用户的行为。
你也许会问,JavaScript为什么是单线程,难道不能实现为多线程吗?
这跟历史有关系。JavaScript从诞生起就是单线程。原因大概是不想让浏览器变得太复杂,因为多线程需要共享资源、且有可能修改彼此的运行结果,对于一种网页脚本语言来说,这就太复杂了。后来就约定俗成,JavaScript为一种单线程语言。(Worker API可以实现多线程,但是JavaScript本身始终是单线程的。)
如果某个任务很耗时,比如涉及很多I/O(输入/输出)操作,那么线程的运行大概是下面的样子。
synchronous mode
由于I/O操作很慢,所以这个线程的大部分运行时间都在空等I/O操作的返回结果。这种运行方式称为"同步模式"(synchronous I/O)或"堵塞模式"(blocking I/O)。
如果采用多线程,同时运行多个任务,那很可能就是下面这样。
synchronous mode
Event Loop就是为了解决这个问题而提出的。Wikipedia这样定义:
"Event Loop是一个程序结构,用于等待和发送消息和事件。(a programming construct that waits for and dispatches events or messages in a program.)"
简单说,就是在程序中设置两个线程:一个负责程序本身的运行,称为"主线程";另一个负责主线程与其他进程(主要是各种I/O操作)的通信,被称为"Event Loop线程"(可以译为"消息线程")。
asynchronous mode
上图主线程的绿色部分,还是表示运行时间,而橙色部分表示空闲时间。每当遇到I/O的时候,主线程就让Event Loop线程去通知相应的I/O程序,然后接着往后运行,所以不存在红色的等待时间。等到I/O程序完成操作,Event Loop线程再把结果返回主线程。主线程就调用事先设定的回调函数,完成整个任务。
可以看到,由于多出了橙色的空闲时间,所以主线程得以运行更多的任务,这就提高了效率。这种运行方式称为"异步模式"(asynchronous I/O)或"非堵塞模式"(non-blocking mode)。
这正是JavaScript语言的运行方式。单线程模型虽然对JavaScript构成了很大的限制,但也因此使它具备了其他语言不具备的优势。如果部署得好,JavaScript程序是不会出现堵塞的,这就是为什么node.js平台可以用很少的资源,应付大流量访问的原因。
1:JS中大量的DOM操作也会导致事件响应缓慢甚至真正卡死浏览器,如在IE6下一次插入大量的HTML。而如果真的弹出了“脚本运行时间过长“的提示框则说明你的JS脚本肯定有死循环或者进行过深的递归操作了。
2:这时候需要对脚本进行优化,其步骤如下:
第一步,优化循环,循环体中包含太多的操作和循环的次数过多都会导致循环执行时间过长,并直接导致锁死浏览器。如果循环之后没有其他操作,每次循环只处理一个数值,而且不依赖于上一次循环的结果则可以对循环进行拆解,看下面的chunk的函数:
function chunk(array, process, context){
setTimeout(function(){
var item = array.shift();
process.call(context, item);
if(array.length 0){
setTimeout(arguments.callee,100);
}),100);
}
chunk()函数的用途就是将一个数组分成小块处理,它接受三个参数:要处理的数组,处理函数以及可选的上下文环境。每次函数都会将数组中第一个对象取出交给process函数处理,如果数组中还有对象没有被处理则启动下一个timer,直到数组处理完。这样可保证脚本不会长时间占用处理机,使浏览器出一个高响应的流畅状态。
其实看来,借助JS强大的闭包机制任何循环都是可拆分的,下面的版本增加了callback机制,使可再循环处理完毕之后进行其他的操作。
function chunk(array,process,cbfun){
var i=0,len = array.length; //这里要注意在执行过程中数组最好是不变的
setTimeout(function(){
process( array[i], i++); //循环体要做的操作
if( i len ){
setTimeout(arguments.callee,100)
}else{
cbfun() //循环结束之后要做的操作
}
}
}
第二步,优化函数,如果函数体内有太多不相干但又要一起执行的操作则可以进行拆分,考虑下面的函数:
function dosomething(){
dosomething1();
dosomething2();
}
dosomething1和dosomething2互不相干,执行没有先后次序,可用前面提到的chunk函数进行拆分:
function dosomething(){
chunk([dosomething1,dosomething2],function(item){item();})
}
或者直接交给浏览器去调度
function dosome(){
setTimeout(dosomething1,0);
setTimeout(dosomething2,0);
}
第三步,优化递归操作,函数递归虽然简单直接但是过深的递归操作不但影响性能而且稍不注意就会导致浏览器弹出脚本失控对话框,必须小心处理。
看以下斐波那契数列的递归算法:
function fibonacci(n){
return n 2? n: fibonacci(n -1)+ fibonacci(n -2);
};
fibonacci(40)这条语句将重复调用自身331160280次,在浏览器中执行必然导致脚本失控,而采用下面的算法则只需要调用40次
fibonacci =function(n){
var memo ={0:0,1:0}; //计算结果缓存
var shell =function(n){
var result = memo[n];
if(typeof result !='number') //如果值没有被计算则进行计算
memo[n]= shell(n-1)+ shell(n -2)
return memo[n];
}
return shell(n);
}
这项技术被称为memoization,他的原理很简单就是同样的结果没必要计算两次。另一种消除递归的办法就是利用迭代,递归和迭代经常会被作为互相弥补的方法。
第四步,减少DOM操作,DOM操作的代价是相当昂贵的,大多数DOM操作都会触发浏览器的回流(reflow)操作。例如添加删除节点,修改元素样式,获取需要经过计算的元素样式等。我们要做的就是尽量少的触发回流操作。
el.style.width ='300px' el.style.height ='300px' el.style.backgroundColor ='red'
上面的操作会触发浏览器的三次回流操作,再看下面的方式:
el.className ='newStyle'
通过设置改元素的className一次设置多个样式属性,将样式写再CSS文件中,只触发一次回流,达到了同样是效果而且效率更高。因为浏览器最擅长的就是根据class设置样式。
还有很多可以减少DOM操作的方法,在此就不多说了,但是一个基本的原则就是让浏览器去做它自己擅长的事情,例如通过class来改变元素的属性。
相信经过上面的优化的过程必定可以大大提高用户体验,不会出现浏览器被锁死和弹出脚本失控的对话框,使你的浏览器从繁重的任务中解放出来。需要指出的是上面这些优化并不是必须的,只有当一段脚本的执行时间真的影响到了用户体验才需要进行。虽然让用户觉得脚本的执行变快了,但其实完成同一个操作的时间可能被延长了,这些技术只是让浏览器处于一个快速响应的状态,使浏览更流畅。