javascript 事件加载与预加载

 更新时间:2009年12月24日 13:15:04   作者:  
本文对JavaScript事件加载进行了一些延伸思考。加载多个事件时,使用window.onload可能会导致一些不便,而通过侦听器等方法,则可以解决这些问题。

通常来说,window.onload就够用了,如果想加载多个事件,我们可以采取以下方式:

复制代码 代码如下:

window.onload = function(){
func1();
func2();
func3();
//更多加载事件………………
}

但如果由于某种特殊需要,我们不能合在一起写吗?如当前区域是面向管理员,后台生成页面时只有当用户是管理员,页面才生成这部分,而这部分也用到一些特殊的脚本,上面的方法就歇菜了!
复制代码 代码如下:

//后台代码
<script type="text/javascript">
window.onload = function(){
func1();
func2();
//加载普通用户用到的脚本……
}
</script>
<%# 以下脚本是为管理员准备的 %>
<% if @user.role == "manager" %>
window.onload = function(){
func1();
func2();
//加载机密脚本……
}
<% end %>

这种情况生成出来的页面拥有两个window.onload代码块,很显然,第二个覆盖掉第一个。这时,轮到loadEvent函数出场了。
复制代码 代码如下:

var loadEvent = function(fn) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = fn;
}else {
window.onload = function() {
oldonload();
fn();
}
}
}

它非常完美地解决了互相覆盖的问题,用法如下:
复制代码 代码如下:

loadEvent(func1);
loadEvent(func2);
loadEvent(func3);
//更多加载事件

但现实的问题总是如此出奇不意,也如此刁钻邪门。最近我想把所有的函数放到一个闭包中,以免除命名冲突之苦,比如那个有名的$的DOM选择器。JQuery,Prototype,mootool都用它做选择器的名字,共存成了个严重的问题。
复制代码 代码如下:

(function(){
if(!window.JS){
window['JS'] = {}
}
var onReady = function(fn){
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = fn;
}else {
window.onload = function() {
oldonload();
fn();
}
}
}
JS.onReady = onReady;
var $ = function(id){
return document.getElementById(id);
}
JS.$ = $;
})()


[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]

不过像这个如此有名的函数其实还有一个缺陷,就是新加载的函数被放置于前一个加载函数的作用域之用,加载函数越多,其栈的层次越深,显然性能耗很大。不过像onclick,onload,onmouseout等这样函数,W3C把它们归属于DOM0的事件模型,好处是适用范围广,但签于其性能,于是又提出DOM1.0的事件模型与DOM2.0的事件模型,DOM2就是原微软的事件模型与原网景的事件模型的合璧,既能捕获又能冒泡,而且多绑定多类型事件而不会导致后者覆盖前者。于是人们总搞出了有名的addEvent函数出来,我们用addEvent来改造我们的事件加载。
复制代码 代码如下:

(function(){
if(!window.JS){
window['JS'] = {}
}
var addEvent = function( obj, type, fn ) {
if (obj.addEventListener)
obj.addEventListener( type, fn, false );
else if (obj.attachEvent) {
obj["e"+type+fn] = fn;
obj.attachEvent( "on"+type, function() {
obj["e"+type+fn]();
} );
}
};
var onReady = function(loadEvent,waitForImages) {
if(waitForImages) {
return addEvent(window, 'load', loadEvent);
}
}
JS.onReady = onReady;
var $ = function(id){
return document.getElementById(id);
}
JS.$ = $;
})()


[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]

OK,没问题。上面的onReady函数有一个可选参数,用于是否待图片加载。我们知道JS引擎会在完成DOM树后才开始处理图片与音频等东西,但如果我们的页面严重依赖于脚本布局呢?!我们想尽快让页面呈现出大体形态,这就用到domReady了。我们在原基础上改进它。
复制代码 代码如下:

(function(){
if(!window.JS){
window['JS'] = {}
}
var addEvent = function( obj, type, fn ) {
if (obj.addEventListener)
obj.addEventListener( type, fn, false );
else if (obj.attachEvent) {
obj["e"+type+fn] = fn;
obj.attachEvent( "on"+type, function() {
obj["e"+type+fn]();
} );
}
};
var onReady = function(loadEvent,waitForImages) {
if(waitForImages) {
return addEvent(window, 'load', loadEvent);
}
var init = function() {
if (arguments.callee.done) return;
arguments.callee.done = true;
loadEvent.apply(document,arguments);
};
if(!+"\v1"){
(function(){
try {
document.documentElement.doScroll("left");
} catch(e) {
setTimeout( arguments.callee, 0 );
return;
}
init();
})();
}else{
document.addEventListener( "DOMContentLoaded", function(){
document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
init();
}, false );
}
return true;
}
JS.onReady = onReady;
var $ = function(id){
return document.getElementById(id);
}
JS.$ = $;
})()

dom标准浏览器用DOMContentLoaded,这是非常正现的W3C论DOM方法,与FF的DOMMouseScroll 不一样,基本上所有非IE内核的浏览器最新版都支持它了。IE下我们可以通过侦听document. documentElement. doScroll()来判断DOM树是否完成,原理是IE下只有当DOM树构建完成后才能doScroll。但它还不是尽善尽美,它在IE下无法判定 iframe的内容是否加载完毕。我们继续改进它。
复制代码 代码如下:

(function(){
if(!window.JS){
window['JS'] = {}
}
var addEvent = function( obj, type, fn ) {
if (obj.addEventListener)
obj.addEventListener( type, fn, false );
else if (obj.attachEvent) {
obj["e"+type+fn] = fn;
obj.attachEvent( "on"+type, function() {
obj["e"+type+fn]();
} );
}
};
var onReady = function(loadEvent,waitForImages) {
if(waitForImages) {
return addEvent(window, 'load', loadEvent);
}
var init = function() {
if (arguments.callee.done) return;
arguments.callee.done = true;
loadEvent.apply(document,arguments);
};
if(!+"\v1"){
if(window.self == window.top){
(function(){
try {
document.documentElement.doScroll("left");
} catch(e) {
setTimeout( arguments.callee, 0 );
return;
}
init();
})();
}else{
document.attachEvent("onreadystatechange", function(){
if ( document.readyState === "complete" ) {
document.detachEvent( "onreadystatechange", arguments.callee );
init();
}
});
}
}else{
document.addEventListener( "DOMContentLoaded", function(){
document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
init();
}, false );
}
return true;
}
JS.onReady = onReady;
var $ = function(id){
return document.getElementById(id);
}
JS.$ = $;
})()

我们简直是在重新实现jquery的$(document).ready(function(){ })!它功能非常强悍,配合利用闭包做成的命名空间,基本刀枪不入。而且它就只污染一个全局变量“JS”,可以与YUI媲美了(笑)。不过对于一般应用来说,我们用不着做到如此面面俱到。假如我们不需要对图片进行处理,页面也没有iframe,我们可以搞下面这个微缩版出来。
复制代码 代码如下:

(function(){
if(!window.JS){
window['JS'] = {}
}
var onReady = function(loadEvent) {
if(!+"\v1"){
(function(){
try {
document.documentElement.doScroll("left");
} catch(e) {
setTimeout( arguments.callee, 0 );
return;
}
loadEvent();
})();
}else{
document.addEventListener( "DOMContentLoaded", loadEvent, false );
}
}
JS.onReady = onReady;
var $ = function(id){
return document.getElementById(id);
}
JS.$ = $;
})()

相关文章

  • 原来JS还可以这样拆箱转换详解

    原来JS还可以这样拆箱转换详解

    这篇文章主要给大家介绍了关于JS拆箱转换的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-02-02
  • 微信企业号开发之微信考勤百度地图定位

    微信企业号开发之微信考勤百度地图定位

    本文给大家介绍微信企业号开发之微信考勤百度地图定位,有需要的朋友参考下本篇文章
    2015-09-09
  • 一文带你搞懂JavaScript中数组的特性

    一文带你搞懂JavaScript中数组的特性

    数组是几乎所有编程语言的基础语法,JavaScript因为语法特性,我们更需要理解数组知识。本文从JavaScript中数组的一些特殊之处入手,通过这些少有特性的详细介绍,加深我们对数组的理解
    2023-04-04
  • js页面引导页的实现思路总结

    js页面引导页的实现思路总结

    在同学们使用某些网站的新版本页面的时候,经常会出现一个类似于新手引导一样的效果,本文主要介绍了js页面引导页的实现思路总结,感兴趣的可以了解一下
    2023-04-04
  • javascript中setAttribute兼容性用法分析

    javascript中setAttribute兼容性用法分析

    这篇文章主要介绍了javascript中setAttribute兼容性用法,结合实例形式分析了javascript使用setAttribute进行属性设置操作的相关使用技巧,需要的朋友可以参考下
    2016-12-12
  • 控制文字内容的显示与隐藏示例

    控制文字内容的显示与隐藏示例

    控制某id或class的地div显示与隐藏是比较容易实现的,但若控制文字内容的显示与隐藏该如何做到呢?下面有个示例,大家可以参考下
    2014-06-06
  • 前端流式输出从原理到实践实现详解

    前端流式输出从原理到实践实现详解

    流式输出技术允许服务器逐步将数据传送给客户端,而不是一次性地加载全部数据,这篇文章主要介绍了前端流式输出从原理到实践实现的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-04-04
  • javascript HTML+CSS实现经典橙色导航菜单

    javascript HTML+CSS实现经典橙色导航菜单

    这篇文章主要介绍了javascript HTML+CSS实现经典橙色导航菜单的相关资料,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • js实现翻页后保持checkbox选中状态的实现方法

    js实现翻页后保持checkbox选中状态的实现方法

    在项目中有需求如下:上下分页后,选中的checkbox状态保持不变
    2012-11-11
  • JS字符串按逗号和回车分隔的方法

    JS字符串按逗号和回车分隔的方法

    下面小编就为大家带来一篇JS字符串按逗号和回车分隔的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04

最新评论