JS事件之事件类型[UI事件]

事件类型

Web浏览器可能发生的事件类型有很多。不同的事件类型具有不同的信息,而“DOM3级事件“规定了以下几类事件。

  • UI(User Interface,用户界面)事件,当用户与页面上的元素交互时触发;
  • 焦点事件,当元素获得或失去焦点时触发;
  • 鼠标事件,当用户通过鼠标在页面执行操作时触发;
  • 滚轮事件,当使用鼠标滚轮(或类似设置)时触发;
  • 文本事件,当在文档中输入文本时触发;
  • 键盘事件,当用户通过包租在页面上执行操作时触发;
  • 合成事件,当为IME(Input MethodEditor,输入法编辑器)输入字符时触发;
  • 变动(mutation)事件,当底层DOM结构发生变化时触发;
  • 变动名称事件,当元素或属性名变动时触发。此类事件已经被废弃,没有任何浏览器实现它们,因此本章不做介绍。

除了这几类事件之外,HTML5也定义了一组事件,而有此浏览器还会在DOM和BOM中实现其他专有事件。这些专有的事件一般都是根据开发人员需求定制的。没有什么规范,因此不同浏览器的实现有可能不一致。
  DOM2级事件模块在DOM2级事件模块基础上重新这些事件,也添加了一些新事件。包括IE9在内的所有主流浏览器都支持DOM2级事件。IE9也支持DOM3级事件。

UI事件

UI事件 批的是那些不一定与用户操作有关的事件。这些事件在DOM规范出现之前,都是以这种或那种形式存在的。而在DOM规范中保留是为了向后兼容。现有的UI的事件如下.

  • DOMActivate:表示元素已经被用户操作(通过鼠标或键盘)激活。这个事件在DOM3级事件中被废弃,但FireFox2+和Chrome支持它。考虑到不同浏览器实现的差异 ,不建议使用这个事件。
  • load:当页面完全加载后在window上面触发,当所有框架都加载完毕时在框架集上面触发,当图像加载完毕时在<img>元素上面触发。或者当嵌入的内容加载完毕时在元素上面触发。
  • unload:当页面完全卸载后在window上面触发,当所有框架都卸载后在框架集上面触发,或者当嵌入的内容卸载完毕后在元素上面触发。
  • abort:在用户停止下载过程时,如果嵌入的内容没有加载完,则在元素上面触发。
  • error: 当发生JavasScript错误时在window上面触发,当无法加载图片时在<img>元素上面触发,当元素加载嵌入内容时在元素上面触发,或者当有一或多个框架无法加载时在框架集上面触发。
  • select: 当用户选择文本框( or )中的一个可多个字符时触发。
  • resize: 当窗口或框架的大小变化时在window或框架上面触发;
  • scroll:当用户流动带有流动条的元素中的内容时,在该元素上面触发。元素中包含所加载页面的流动条。

多数这些事件都与window对象或表彰控件相关。

除了DOMActivate之外,其他事件都在DOM2级事件中都归为HTML事件(DOMActivate在DOM2级中仍然属于UI事件)。在确定浏览器是否支持DOM2级事件规定的HTML事件,可以使用如下代码:

var isSupported = document.implementation.hasFeature('HTMLEvents',"2.0");

注意,只有根据“DOM2级事件”实现这此事件的浏览器才会返回true。而以非标准方式支持这些事件的浏览器则会返回false。要确定浏览器是否支持“DOM3级事件”定义的事件,可以使用如下代码:

var isSupported = document.implementation.hasFeature('HTMLEvents',"3.0");

1、load事件

JavaScript中最常用的一个事件就是load。当页面完全载后(包括所有图像、JavasScript文件、CSS文件等外部资源),就会触发window上面的load事件。有二种定义onload事件处理程序的方式。

第一种方式是使用如下所示的JavasScript代码:

EventUtil.addHandler(window,'load', function(event){
    alert("Loaded");
})
//注意EventUtil对象是自定义封装的一个对象

这是通过JavasScript来指定事件处理程序的方式,使用了本章前面定义的跨浏览器的EventUtil对象。与添加其他事件一样,这里也给事件处理程序传入了一个event对象。这个event对象中不包含有关这个事件的任何附加信息,但兼容DOM的浏览器中,event.target属性的值会被设置为document.而IE并不会为这个事件设置srcElement属性。

第二种指定onload事件处理程序的方式是为元素添加一个onload特性,如下面例子所示:

<body onload="alert('Loaded')">

</body>

一般来说,在window上面发生的任何事件都可以在元素中通过相应的特性来指定。因为在HTML中无法访问window元素。初阶上,这只是为了保证向后兼容的一种权宜之计,但所有浏览器都能很好地支持这种方式。我们建议读者尽可能使用javascript方式。
  根据“DOM2级事件”规范,应该在document而非window上面触发load事件,但是,所有浏览器都在window上面实现了该事件,以确保向后兼容。

图像上面也可以触发load事件,无论是在DOM中的图像还是HTML中的图像元素。 可以在HTML中为任何图像指定onload事件处理程序,例如:

<img src="smile.gif" onload="alert('Image loaded')">

这样,当例子中的图像加载完毕后就会显示一个警告框。同样的功能也可以使用JavasScript来实现,例如:

var image = document.getElementById('myImage');
EventUtil.addHandler(img,'load', function(evnet){
    event = EventUtil.getEvent(event);
    alert(EventUtil.getTarget(event).src);
})

这里,使用JavasScript指定了onload事件处理程序。同时民传入了event对象,尽管它也不包含什么有用的信息。不过,事件的目标是<img>元素。可以通过src属性访问并显示该 信息。

在创建新的<img>元素时,可以为其指定一个事件处理程序,以便图像加载完毕后给出提示。此时,最重要在指定src属性之前先指定事件,如下面的例子所示。

EventUtil.addHandler(window,'load', function(){
    var image = document.getElementById('myImage');

    EventUtil.addHandler(img,'load', function(){
        event = EventUtil.getEvent(event);
        alert(EventUtil.getTarget(event).src);
    });

    document.body.appendChild(image);
    image.src = 'smile.gif';
})

在这个例子中,首先为window指定了onload事件处理程序。原因在于,我们是想向DOM中添加一个新元素,所以必须确定页面已经加载完毕——如果在页面加载前操作document.body会导致错误。然后,创建了一个新的图像元素,并设置了其onload事件处理程序。最后又将这个图片添加到页面中,还设置了它的src属性。这里有一点需要格外注意:新图像元素不一定要从添加到文档后才开始下载,只要设置了src属性就会开始下载。

同样的功能也可以通过使用DOM0级的Image对象实现。在DOM出现之前,开发人员经常使用Image对象在客户端预先加载图像。可以像使用<img>一样使用Image对象,只不过无法将其添加到DOM树中。下面看一个例子:

EventUtil.addHandler(window,'load', function(){
    var image = new Image();

    EventUtil.addHandler(img,'load', function(){
        alert("Image loaded!");
    });

    image.src = 'smile.gif';
})

在此,我们使用Image构造函数创建了一个新图像的实例,然后又为它指定了事件处理程序。有的浏览器将Image对象实现了<img>元素,但并非所有浏览器都如此,所以最好将它们区别对待。
  在不属于DOM文档的图像(包括未添加到文档的元素和Image对象)上触发load事件时,IE8及之前版本不会生成event对象。IE9修复了这个问题

还有一些元素也以非标准的方式支持load事件。在ie9+ foxfire Opera Chrome和Safari3+及更高版本中。<script>元素也会触发load事件,以便 开发人员确定动态加载的JavasScript文件是否加载完毕。 与图像不同,只有在设置了<script>
元素的src属性并将该元素添加到文档后,才会开始下载JavasScript文件。换句放说,对于元素而言,指定src属性和指定事件处理程序的先后顺序就不重要了,所有代码展示了怎样为<script>元素指定事件处理程序。

EventUtil.addHandler(window,'load', function(){
    var script  = document.createElement('script');
    EventUtil.addHandler(script,'load', function(){
        alert('Loaded');
    });

    script.src = "examplte.js";
    document.body.appendChild(script);
})

这个例子使用了跨浏览器的EventUtil对象为新创建的<script>元素指定了onload事件处理程序。此时,大多数浏览器中event对象的target属性引用的都是<script>节点,而Foxfire3之前的版本中,引用的则是document。IE8及更早版本不支持<script>元素上的load元素。

IE和Opera还支持<link>元素上的load事件,以便开发人员确定样式表是否加载完毕。例如:

EventUtil.addHandler(window,'load', function(){
    var link  = document.createElement('link');
    link.type="text/css";
    link.rel="stylesheet";
    EventUtil.addHandler(link,'load', function(){
        alert('css Loaded');
    });

    link.src = "examplte.css";
    document.getElementsByTagName('head')[0].appendChild(link);
})

<script>节点类似,在未指定href属性并将<link>元素添加到文档之前也不会开始下载样式表。

2、unload事件

与load事件对应的是 unload事件,这个事件在文档被完全卸载后触发。只要用户从一个页面切换到另一个页面,就会发生unload事件。而利用这个事件最多的情况是清除引用,以避免内在泄漏。与load事件类似,也两种指定onunload事件处理程序方式。第一种方式是使用JavasScript,如下所示:

EventUtil.addHandler(window,'unload', function(){
    alert('Unloaded');
})

此时生成的event对象在兼容DOM的浏览器中只包含target属性(值为document)。IE8及之前版本则为这个事件对象提供了srElement属性。

指定事件处理程序的第二种方式,民是为<body>元素添加一个特性(与load事件相似),如下面的例子所示:

<body onunload="alert("Unloaded")"></body>

无论使用哪种方式,都要小心编写onunload事件处理程序中的代码。既然unload事件是在一切都被卸载后才触发 ,那么在页面加载后存在的那些对象,此时就不一定存在了。此时,操作DOM节点或元素的样式就会导致错误。

根据“DOM2级事件”,应该在<body>元素而非window对象上面触发unload事件。不过所有浏览器都在window上实现了unload事件,以确保向后兼容。

3、resize事件

当浏览器窗口被调整到一个新的高度或宽度时,就会触发resize事件。这个事件在window(窗口)上面触发,因此可以通过JavasScript或者<bdoy>元素中的onresize特性来指定事件处理程序。如前所述,我们还是推荐使用如下所示的JavasScript方式:

EventUtil.addHandler(window,'resize', function(){
    alert('Resizeed');
})

与其他发生在window上的事件类似,在兼容DOM的浏览器中,传入事件处理程序中event对象有一个target属性,值为document;而IE8及之前版本则未提供任何属性。

关于何时会触发resize事件,不同浏览器有不同的机制。IE Safari Chrome 和 Opera会在浏览器窗口变化了1像素时就触发 resize事件,然后随着变化不断重复触发。FIrefox则只会在用户停止调整窗口变化时才会触发 resize事件。由于 存在这个差别,应该注意不要在这个事件的处理程序中加入大计算的代码。因为这些代码有可能被频繁执行,从而导致浏览器反应明显变慢。

浏览器窗口最小化或最大化时也会触发 resize事件

4、scroll事件

虽然scroll事件是在window对象上发生的,但它实际表示的则是页面中相应元素的变化。在混杂模式下,可以通过 <body>元素的scrollLeft和scrollTop来监控到这一变化;而在标准 模式下,除Safari之外的所有浏览器都会通过<html>元素来反映这一变化(Safari仍然基于<body>跟踪滚动位置),如下面的例子所示:

EventUtil.addHandler(window,'scroll', function(){
    if(documnent.compatMode == 'CSS1Compat') {
        alert(document.documentElement.scrollTop);
    } else {
        alert(document.body.scrollTop);
    }
})

以上代码指定的事件处理程序会输出页面的垂直滚动位置—–根据呈现模式不同使用了不同的元素。 由于 Safari3.1之前的版本不支持document.compatMode,因此旧版本的浏览器就不会满足第二个条件。

与resize事件类似,scroll事件也会在文档被滚动期间重复被触发,所以有必要尽量保持事件处理程序的代码简单。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容

  • JavaScript 程序采用了异步事件驱动编程模型。在这种程序设计风格下,当文档、浏览器、元素或与之相关的对象发...
    劼哥stone阅读 1,250评论 3 11
  • 事件流 IE和Netscape开发团队提出了完全相反的两种事件流的概念,事件冒泡流和事件捕获流。 事件冒泡 事件由...
    exialym阅读 924评论 0 9
  • 1.几种基本数据类型?复杂数据类型?值类型和引用数据类型?堆栈数据结构? 基本数据类型:Undefined、Nul...
    极乐君阅读 5,498评论 0 106
  • 声明:本文来源于http://www.webzsky.com/?p=731我只是在这里作为自己的学习笔记整理一下(...
    angryyan阅读 6,941评论 1 6
  • 学习是一种什么样的体验? 学习对我来说,是醍醐灌顶的自我顿悟,来自更高场域的人对你说的一句话,让你瞬间开启了更大的...
    蔡蔡1988阅读 417评论 0 3