月度存档: 一月 2007

设计的选择:window.onload or other

在网页设计中,总要用到一些动态效果,而这些效果之中,有一些是需要页面加载完成时才可以做的,比如要给页面中的每一个链接加上hover时的特效,那么就需要在页面的所有代码已经下载完毕时再进行特效,这样才能保证页面里的每一个链接都不会遗漏。如果这步工作放在head中,那么,做与不做一个样。

再者,现在网页设计讲究行为、结构、表现分离,比如在最近的一次改版中,我把我的blog侧边栏的展开与折叠的功能放在了JS中添加,并不是在源代码里直接设置onclick事件添加好的。因为函数调用不是直接直接而是后来添加的,我就要考虑什么时候来用JS添加侧边栏的展开与折叠了。

功能的添加函数所在的脚本放在了head区引入,当然不能在脚本里直接调用这个函数来进行功能的添加,因为那个时候边栏还没有加载,用document.getElementById会出现找不到对象的错误,然后边栏的展开与折叠功能就没有。

那么,从这一点知道,功能的添加是需要在要处理的内容已经加载完成的情况下才能添加

那什么时候侧边栏已经加载完毕了呢,许多人自然而然地就想到了window.onload。是的,在window.onload被调用时,整个页面已经加载完成,那么边栏也一定加载完毕,这个时候做添加onclick响应函数是肯定不会出现找不到对象的错误的。

<html>
<head>
<meta name=”author” content=”www.xujiwei.cn” />
<meta name=”description” content=”ue test from xujiwei” />
<title>ue test1</title>
<style type=”text/css”>
#blockHead {
background: blue; color: white; width: 300px; padding: 1em; cursor: pointer; border: 1px solid blue;
}
#blockContent {
border: 1px solid blue; width: 300px; padding: 1em;
}
</style>
<script type=”text/javascript”>
window.onload=function() {
document.getElementById(“blockHead”).onclick=function() {
if(document.getElementById(“blockContent”).style.display==””)
document.getElementById(“blockContent”).style.display=”none”;
else
document.getElementById(“blockContent”).style.display=””;
}
}
</script>
</head>
<body>
<div id=”blockHead”>block Head</div>
<div id=”blockContent”><img src=”http://www.xujiwei.cn/logo.gif” alt=”hotheart” />block Content</div>
</body>
</html>

如此,便给边栏的Member模块加上了折叠功能。但是,onload会是最好的选择吗?

回答是否定的,为什么,因为window.onload只有在整个页面完全加载完成,包括一些因为网速或者链接失效的内容也全部加载完成或者确认无效时才会被调用。那么,万一,如果这个页面里有某些元素由于某些原因而得不到及时的加载,就会延长整个页面的加载时间,window.onload的执行时刻也会相应的往后移。譬如下面这段:

<html>

<head>

<meta name=”author” content=”www.xujiwei.cn” />

<meta name=”description” content=”ue test from xujiwei” />

<title>ue test2</title>

<style type=”text/css”>

#blockHead {

background: blue; color: white; width: 300px; padding: 1em; cursor: pointer; border: 1px solid blue;

}

#blockContent {

border: 1px solid blue; width: 300px; padding: 1em;

}

</style>

<script type=”text/javascript”>

window.onload=function() {

document.getElementById(“blockHead”).onclick=function() {

if(document.getElementById(“blockContent”).style.display==””)

document.getElementById(“blockContent”).style.display=”none”;

else

document.getElementById(“blockContent”).style.display=””;

}

}

</script>

</head>

<body>

<div id=”blockHead”>block Head</div>

<div id=”blockContent”><img src=”http://www.xujiwei.c_n/logo.gif” alt=”hotheart” />block Content</div>

</body>

</html>

因为http://www.xujiwei.c_n/logo.gif中的域名是不合法的(域名中不可以包含下划线),但是浏览器不会去判断,仍旧照常去解析,然后出现不可到达的错误,再用图片的替代文本来代替图片,这需要时间。在这段时间里,window.onload都不会执行,因为浏览器认为页面还没有加载完成,所以还不是调用window.onload的时候,也就是说,这个折叠功能一直没有添加

但是用户的操作不会受这一点内容的影响。在整个页面的轮廓出来以后,用户就会开始做自己要做的事,而不会等到浏览器确认那一点点的东西是不可以成功加载的,执行完window.onload才去做自己要做的事。

换句话说,就是这些功能的添加要在用户觉得他可以做他自己要做的事之前进行,中间不能因为一些未知的原因而搁置。那么,这些功能的添加应该放在什么位置?我的做法是在页面的HTML已经载入时去调用功能添加函数,再加上HTML语法规则,把功能添加函数的调用放在了body标签结束之前,即:

<html>

<head>

<meta name=”author” content=”www.xujiwei.cn” />

<meta name=”description” content=”ue test from xujiwei” />

<title>ue test3</title>

<style type=”text/css”>

#blockHead {

background: blue; color: white; width: 300px; padding: 1em; cursor: pointer; border: 1px solid blue;

}

#blockContent {

border: 1px solid blue; width: 300px; padding: 1em;

}

</style>

<script type=”text/javascript”>

function initApp() {

document.getElementById(“blockHead”).onclick=function() {

if(document.getElementById(“blockContent”).style.display==””)

document.getElementById(“blockContent”).style.display=”none”;

else

document.getElementById(“blockContent”).style.display=””;

}

}

</script>

</head>

<body>

<div id=”blockHead”>block Head</div>

<div id=”blockContent”><img src=”http://www.xujiwei.c_n/logo.gif” alt=”hotheart” />block Content</div>

<script type=”text/javascript”>

initApp();

</script>

</body>

</html>

这个时候,虽然浏览器仍然在试图解析www.xujiwei.c_n,去下载logo.gif,但是折叠功能已经成功添加了,用户进行他的操作已经没有问题,至于那张图片是否能显示出来,已经不会影响用户对整个页面的使用。

在test1中,可以看出如果整体页面中没有影响页面加载的内容,那么window.onload进行页面功能添加也是可以的,但是现在的网页做出来谁能保证其中的内容一直有效呢,于是在test2中可以看到如果页面中有加载不了的内容,window.onload可能会在用户离开页面之后还没有执行,就因为那么一点内容加载不了,导致window.onload不能执行,接着就是一些功能用户不能用,接着用户感觉就不好,接着用户就离开了本页。而在test3中,没有把功能的添加放在window.onload中,而是放在了页面代码的末尾,那么即不会在执行功能添加函数时,出现找不到对象的错误,也不会因为页面一点加载不了的内容而影响功能的添加,用户能感觉到的只是有那么一点点内容可能因为时间或者其他一些原因失效而不能加载,但这并不影响他对整个页面的使用。

当然,选择在哪个地方进行页面功能的添加是个仁者见仁,智者见智的问题。每个人的需要不同,处理方法也会相应的不同。我比较倾向于把页面中关键功能的部分放在body结束标签之前,而其他一些修饰性的功能如果给链接加上修饰性的title等放在window.onload,这样即不会影响使用又能有较好的页面效果。

如果大家有什么好的想法可以一起讨论,我的邮箱vipxjw[at]163[dot]com。

VBScript中变量作用域

下午在写程序的时候,碰到个变量重定义的问题,具体是在一个函数中的两个地方定义了相同的变量,两个变量分别放在IF语句的两部分中,本来以为这两次定义在语句中不同的块,应该没有影响,然而在运行中IIS却提示变量重定义,把重复定义去掉即正确。

解决了问题之后突然想到在Fdream的blog看过一篇文章《JavaScript变量无块级作用域》,似乎这两个是差不多的,在VBScript中变量同样没有块级作用域

再次去看了那篇文章之后我也做了下试验,得到结果:在VBScript中,函数中定义的变量的作用域是整个函数,而不是块级,不管这个变量是在函数中哪个位置定义的。因此,函数中一个变量不管在函数的哪个位置定义,它在整个函数中都可以使用。

下面用一些例子来说明这个问题。

Option Explicit
Sub foo()
Dim var
var=”hello,world!”
MsgBox var
End Sub
Call foo()

下面的代码跟上面的代码等效,但是var的定义放在了函数的最后:

Option Explicit
Sub foo()
var=”hello,world!”
MsgBox var
Dim var
End Sub
Call foo()

下面的例子说明变量不管在哪定义,在整个函数中都是可以使用的,当然如果把定义的位置放的特殊一点有利于代码的清晰,阅读起来比较方便,修改时也比较方便。

Option Explicit
Sub foo()
Dim var1
var1=”YES”
MsgBox “var1: “&var1&vbCrLf&”var2: “&var2
IF var1=”YES” Then
Dim var2
var2=”NO”
End IF
MsgBox “var1: “&var1&vbCrLf&”var2: “&var2
End Sub
Call foo()

在ASP开发中,写一个函数时通常的做法是变量到用时才定义,虽然变量的作用域与定义的位置无关,不过我觉得还是写在变量使用之前比较好,以后改起代码来比较方便,不至于修改了一段代码之后还要翻到函数头去修改变量定义。