JavaScript事件

1.事件流

1.1事件冒泡

IE的事件流叫做事件冒泡,事件开始时由最具体的元素节点接收,逐步向上传播。

<!DOCTYPE html>
<html>
<head>
    <title>Event Bubbling Example</title>
</head>
<body>
    <div id="myDiv">Click Me</div>
</body>
</html>

如果你在div设置了一个点击事件,则传播顺序:1.div 2.body 3.html 4.document

1.2 事件捕获

不太具体的节点应该更早的接收事件。在事件达到预期目标之前捕获它。
仍然是上面的例子,事件捕获顺序:1.document 2.html 3.body 4.div

1.3 DOM事件流

DOM事件流分为三个阶段:事件捕获、目标阶段、事件冒泡。


2.事件处理程序

事件是用户或者浏览器自身执行的动作。响应某个事件的函数叫做事件处理程序。

2.1 HTML事件处理程序

通过html的方式实现一个onclick事件

<input type = "button" onclick = "alert("hellp")">
2.2 DOM0级事件处理程序

这也是现在最常用的一种方法。为啥常用?原因一是简单,原因二具有跨浏览器优势。

var btn = document.getElementById("myBtn");
btn.onclick = function () {
    alert("hello");
};
2.3 DOM2级事件处理程序

“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener()和removeEventListener()。
所有的DOM节点都包含这两个方法。接收三个参数:要处理的时间名、作为事件处理程序的函数和布尔值。最后这个布尔值是true,表示在捕获节点调用时间处理程序;如果是false,表示在冒泡阶段调用时间处理程序。

var btn = document.getElementById("myBtn");
btn.addEventListener("click", function(){
    alert(this.id);
}, false);

btn.addEventListener("click", function(){
    alert("Hello world!");
}, false);
2.4 IE事件处理程序

IE实现了DOM中类似的两个方法:attachEvent()和detachEvent()。这两个方法接收相同的两个参数:事件处理程序名称与时间处理程序函数。IE8及更早的版本只支持事件冒泡,所以通过attachEvent()添加的时间处理程序都会被添加到冒泡阶段。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
    alert("Clicked");
});
btn.attachEvent("onclick", function(){
    alert("Hello world!");
});
2.5 跨浏览器的事件处理程序

要保证处理事件的带啊能在大多数浏览器下一致的执行,只需要关注冒泡阶段。
第一个要创建的放大是addHandler(),它的作用是视情况而定分别使用DOM0级方法、DOM2级方法或IE方法来添加事件。addHandle()接受三个参数:要操作的元素、事件名称和事件处理程序函数。

var EventUtil = {
    addHandler: function(element, type, handler){
        if (element.addEventListener){
            element.addEventListener(type, handler, false);
        } else if (element.attachEvent){
            element.attachEvent("on" + type, handler);
        } else {
            element["on" + type] = handler;
        }
    },
    removeHandler: function(element, type, handler){
        if (element.removeEventListener){
            element.removeEventListener(type, handler, false);
        } else if (element.detachEvent){
            element.detachEvent("on" + type, handler);
        } else {
            element["on" + type] = null;
} }
};

3.事件对象

在触发DOM上的某个事件时,会产生一个event对象,这个对象中包含素有时间有关的信息。事件的元素、事件的类型及其他相关信息。例如,鼠标点击导致的事件,可以获取到鼠标点击的位置;键盘操作导致的事件,会包含与按下的键有关的信息。

3.1 DOM中的时间对象

兼容DOM的浏览器会将一个event对象传入到时间处理程序中。无论指定时间处理程序时使用什么方法,都会传入event对象。

var btn = document.getElementById("myBtn");
btn.onclick = function(event){ 
    alert(event.type);          //"click"
};

btn.addEventListener("click", function(event){
    alert(event.type);          //"click"
}, false);

关于Event对象包含的属性与方法

属性/方法 类型 读/写 说明
bubbles boolean 只读 表明时间是否冒泡
cancelable boolean 只读 表名是否可以取消事件默认行为
currentTarget Element 只读 其事件处理程序当前正在处理事件的那个元素
defaultPrevented boolean 只读 为true表示已经调用了preventDefault()
detail Integer 只读 与事件相关的细节信息
eventPhase Integer 只读 调用时间处理程序的阶段,1表示捕获阶段,2表示处于目标,3表示冒泡阶段
preventDefault() Function 只读 取消事件默认行为
stopImmediatePropagation() Function 只读 取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用
stopPropagation() Function 只读 取消事件的进一步捕获或冒泡,如果bubbles为true,则可以使用这个方法
target Element 只读 事件的目标
trusted boolean 只读 为true表示事件是浏览器生成。false表示事件使用开发人员通过JS创建
type String 只读 被触发事件的类型
view AbstractView 只读 与事件关联的抽象视图。等同于发生事件的window对象

在对象处理程序内部,对象this扥估currentTarget的值。

var btn = document.getElementById("myBtn");
btn.onclick = function(event) {
    alert(event.currentTarget === this);    //true
    alert(event.target === this);           //true
};

4.事件类型

事件类型分类:UI事件、焦点事件、鼠标事件、滚轮事件、文本事件、键盘事件、合成事件、变动事件。

4.1 UI事件

1.load事件:JS中最常用的就是load事件。当页面加载后就会触发window上的load事件。如何定义onload事件呢?可以看下demo

第一种,JS声明
EventUtil.addHandler(window, "load", function(event){
   alert("Loaded"); 
});

第二种,标签属性
<body onload="alert('Loaded!')">

2.unload事件:文档被完全卸载后触发。只要用户从一个页面切换到另一个页面就会触发unload。利用这个事件最多的情况是清除引用,避免内存泄露。

第一种,JS声明
EventUtil.addHandler(window, "unload", function(event){
        alert("Unloaded");
});

第二种,标签属性
<body onunload="alert('Loaded!')">

3.resize事件:当浏览器窗口被调整到一个新的高度或宽度时,就会触发resize事件。注意resize事件会频繁被触发,所以在尽量不要书写大量运算逻辑,会导致浏览器变慢。

第一种,JS声明
EventUtil.addHandler(window, "resize", function(event){
        alert("Resized");
});

第二种,标签属性
<body onresize="alert('Loaded!')">

4.scroll事件:当用户滚动带滚动条的元素内容时触发。在window对象上发生的,表示页面中响应元素的变化。跟resize事件类似,scroll会频发触发。所以在尽量不要书写大量运算逻辑,会导致浏览器变慢

EventUtil.addHandler(window, "scroll", function(event){
    if (document.compatMode == "CSS1Compat"){
        alert(document.documentElement.scrollTop);
    } else {
        alert(document.body.scrollTop);
    }
});
4.2 焦点事件(这里就不写demo了,会对事件做一个详细的分析)
  • blur:在元素市区焦点时触发。这个事件不会冒泡(但是可以捕获阶段监听到)
  • focus:在元素获得焦点时触发。这个事件不会冒泡(但是可以捕获阶段监听到)
  • focusion:在元素获得焦点时触发。这个事件会冒泡
  • focusout:在元素失去焦点时触发。这个事件会冒泡
4.3 滚动与滚轮事件
  • click:在用户单击主鼠标按钮或者回车键触发
  • dblclick:在用户双击主鼠标按钮时触发
  • mousedown:在用户按下任意鼠标按钮时触发。
  • mouseenter:鼠标光标从元素外部首次移动到元素范围内触发。(IE、Firefox 9+和Opera支持)
  • mouseleave:在位于元素上方的鼠标光标移动到元素范围之外时候触发。(IE、Firefox 9+和Opera支持)
  • mousemove:当鼠标指针在元素内部移动时重复触发。
  • mouseout:在鼠标指针位于一个元素上方,然后用户将其移入另一个元素时触发。
  • mouseover:在鼠标指针位于一个元素外部,然后用户将其移入另一个元素边界之内时触发。
  • mouseup:在用户释放鼠标按钮时触发。

1.客户区坐标位置(整个浏览器去掉工具栏等其他辅助工具的位置)

var div = document.getElementById("MyDiv");
EventUtil.addHandler(div, "click", function(event){
    event = EventUtil.getEvent(event);
    alert("Client coordinates: " + event.clientX + "," + event.clientY);
});

2.页面坐标位置

var div = document.getElementById("MyDiv");
EventUtil.addHandler(div, "click", function(event){
    event = EventUtil.getEvent(event);
    alert("Page coordinates: " + event.pageX + "," + event.pageY);
});

3.屏幕坐标位置(获取的是整个用户操作系统界面的坐标)

var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "click", function(event){
    event = EventUtil.getEvent(event);
    alert("Screen coordinates: " + event.screenX + "," + event.screenY);
});

4.修改键
修改键就是Shift、Ctrl、Alt,这些经常被用来修改鼠标性情。因此DOM规定了四个属性,来修改这些按键的状态:shiftKey、ctrlKey、altKey和metaKey。这些属性都是布尔值,如果这些按键按下了则为true,否则为false。

var div = document.getElementById("myDiv");
EventUtil.addHandler(div, "click", function(event){
    event = EventUtil.getEvent(event);
    var keys = new Array();
    if (event.shiftKey){
        keys.push("shift");
}
    if (event.ctrlKey){
        keys.push("ctrl");
}
    if (event.altKey){
        keys.push("alt");
}
    if (event.metaKey){
        keys.push("meta");
}
    alert("Keys: " + keys.join(","));
});
4.4 键盘与文本事件
  • keydown:当用户按下键盘上任意键时触发。按住不放,重复执行此事件
  • keypress:当用户按下键盘上的字符键时触发。按住不放,重复执行此事件
  • keyup:当用户释放按键时触发

1.键码
键盘上每个按键都有一个keyCode属性用于标识按键的。

var textbox = document.getElementById("myText");
EventUtil.addHandler(textbox, "keyup", function(event){
    event = EventUtil.getEvent(event);
    alert(event.keyCode);
}); 

2.字符编码
浏览器event对象都支持一个charCode属性,这个属性只有在发生keypress事件才有值,而且这个值是安县哪个键锁代表的字符的ASCII编码。通常用来检验浏览器字符集。

3.textInput事件
用户在可编辑区域中输入字符时,就会触发这个事件。

var textbox = document.getElementById("myText");
EventUtil.addHandler(textbox, "textInput", function(event){ event = EventUtil.getEvent(event);
alert(event.data);
}); 

5.内存与性能

5.1 事件委托

对事件处理程序过多的时候,就可以通过委托的方式去解决。事件委托利用了事件冒泡。指定一个事件处理程序,就可以管理一类型所有的事件。

<ul id="myLinks">
    <li id="goSomewhere">Go somewhere</li>
    <li id="doSomething">Do something</li>
    <li id="sayHi">Say hi</li>
</ul>


function getEvent(){
    var list = document.getElementById("myLinks");
    EventUtil.addHandler(list, "click", function(event){
        event = EventUtil.getEvent(event);
        var target = EventUtil.getTarget(event);
    }
}

5.2 移除事件处理程序

每当事件处理程序指定元素时,运行中的浏览器代码与支持页面交互的JS代码会建立一个链接。这种链接越多,页面执行越慢。可以两种方式规避这个问题,可以采用事件委托技术限制建立连接数。另外,在不需要的时候移除事件处理程序。

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

推荐阅读更多精彩内容

  •   JavaScript 与 HTML 之间的交互是通过事件实现的。   事件,就是文档或浏览器窗口中发生的一些特...
    霜天晓阅读 3,470评论 1 11
  • JavaScript 与 HTML 之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些特定的交互瞬...
    threetowns阅读 339评论 0 0
  • 事件处理程序在应用中是必不可少的,虽然现在很多框架都有自己实现事件处理方法,但是熟知原生才能让我们应对各种各样的需...
    俗三疯阅读 282评论 0 1
  • 事件类型 Web 浏览器中可能发生的事件有很多类型UI事件:当用户与界面上的元素交互时触发。焦点事件:当元素获得或...
    shanruopeng阅读 901评论 0 0
  • 事件流 事件流描述的是从页面中接受事件的顺序。但是IE和Netscape开发团队提出了差不多相反的事件流的概念。I...
    losspm阅读 260评论 0 0