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来改变元素的属性。
相信经过上面的优化的过程必定可以大大提高用户体验,不会出现浏览器被锁死和弹出脚本失控的对话框,使你的浏览器从繁重的任务中解放出来。需要指出的是上面这些优化并不是必须的,只有当一段脚本的执行时间真的影响到了用户体验才需要进行。虽然让用户觉得脚本的执行变快了,但其实完成同一个操作的时间可能被延长了,这些技术只是让浏览器处于一个快速响应的状态,使浏览更流畅。
载入脚本或者脚本在执行了一些较多的页面载入完成的事件 可能由于js文件未完全载入导致假死刷新之后可能文件载入完成操作就正常了
泽元的框架太大了 压缩之后还100多k
建议使用我的框架http://hi.baidu.com/zkunet/blog/item/01cf700f1d3f49c17acbe1a2.html
第二关于弹出层的问题 我也自己写了一个(当然参考了泽元的代码 修正泽元的bug 具体bug就不指出了) 当然ui是用的泽元的 我发给你代码
图片相信你自己有就不用我给你了吧
注意:上面的框架不要和下面的弹出层放一起 我没有做检查 有些函数可能在我的框架里已经有了 可能导致冲突报错 等以后检查了 再到我的空间来看
/*xs.Dialog.js 作者:肖毅 转载请保留这段申明 http://hi.baidu.com/zkunet/ */
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:leftfont-weight:boldcolor:#FFFFFFpadding:9px 0 0 4pxfont-size:12px'>")
arr.push("<img src='"+PicPath+"icon_dialog.gif' align='absmiddle'> "+this.Title+"</div>")
arr.push("<div style='position: relativecursor:pointerfloat:rightmargin:5px 0 0_margin:4px 0 0height:17pxwidth:28pxbackground: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("<tr><td 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:16pxpadding-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("<tr><td 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: #transparentborder:noneoverflow-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:rightborder-top:#dadee5 1px solidpadding:8px 20pxbackground-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></td><td width='13' style='background:url("+PicPath+"dialog_mrm.png)background-repeat:no-repeat'></td></tr>")
arr.push("<tr><td 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("<tr><td 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(k<5) {
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.length>1) {
for(i=0i<pw.Dialog._Array.length-1i++) {
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.length>0) {
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.clientX<sl || pw.event.clientY<st || pw.event.clientX>sr || pw.event.clientY>sb) {
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=0i<DialogArr.lengthi++){
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.length>0){
stopEvent(window.event)
}
}
if(window.event.keyCode==27){
if(pw.Dialog._Array.length>0){
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)
}