鼠标经过和离开事件,这两个事件怎么在同一个函数中定义,没看懂

问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
在JS高级程序设计里,解释是:事件就是文档浏览器窗口中发生的一些特定的交互瞬间。感觉这对新手来说,书上的解释还是不能很好理解,还是不是很具体。一说事件大家知道点击事件,鼠标事件等等,但是我查了资料还是不能像同学解释清楚什么是事件?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
我觉得已经够通俗了,如果再通俗点:
事件就是你在浏览器上浏览网页时做出的“行为”,可以把任何操作都看作行为(点击,滑动等等),毕竟你不可能坐在电脑前一动不动吧!
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
不如解释成动作吧,指定的动作对应指定的处理函数,叫事件也没什么不好理解的吧,难道会和那种订阅/发布的事件混淆?其实也差不多啊,绑定处理函数相当于(subscribe),各种交互触发相当发布(dispatch)。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
事件就是消息。进一步说,就是提前约定好的具有特定格式和含义的消息。
当你收到一条消息时,意味着你需要去某件事情来响应这条消息了。
举例:智能手机的闹钟功能
你设定一个闹钟用来提醒你起床,又设定一个闹钟提醒你吃午饭,又设定一个闹钟提醒你去跑步。
当闹钟响起时,就意味着你收到一条消息(或者说发生了一个事件)。根据消息(事件)的具体内容,比如name='跑步',你就可以知道你需要做什么了。你要做的事情就是对这个事件的响应。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
JS 里的事件基本分类
元素事件-HTMLEvents [change,click,...]
鼠标事件-MouseEvents
[mousemove,mousedown,mouseup,mouseover]
键盘事件-KeyboardEvents [keydown, keypress, keyup]
一个典型的事件绑定及解绑函数
function bind(elem, event, func, bool) {
bool = bool ||
if (elem.addEventListener)
elem.addEventListener(event, func, bool);
else if (elem.attachEvent)
elem.attachEvent('on' + event, func);
function unbind(elem, event, func, bool) {
bool = bool ||
if (elem.removeEventListener)
elem.removeEventListener(event, func, bool);
else if (elem.detachEvent)
elem.detachEvent('on' + event, func);
事件模型, IE和其他浏览器采用了不同的方案来处理,一个是从上往下,另一个是从事件发生的元素向上传递通知事件。
一般的事件处理模型
选择DOM树中的元素,监听事件,用户触发事件,调用事件的回调函数处理事件。
创建自定义的事件,当对象发生改变时,触发事件,通知已注册的回调函数。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
事件就是消息,就是广播~~~消息有特定目标的消息和无具体目标的消息消息发送出去了,可以有人响应,也可能没人理睬想要收到消息,那么就需要订阅,就需要addEventListener
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
just only do something.
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
事件就是些约定好的动作
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
既然说到形象,那我就把我们浏览的页面比喻成见一个朋友吧。朋友一见到你,向你打招呼。在这个过程中,见到你对这个朋友来说就是一个事件,这个事件包含了你这个人的信息,见到你的时间地点等等;向你打招呼就是见到你这个事件的回调函数结果啦,他根据事件中你的个人信息和其他信息,决定是否要和你打招呼,怎么跟你打招呼,是不是要吓你一跳等等。--& 相当于body的onload事件朋友和你打招呼之后,你们开始聊天。你问他:“最近过得怎么样?”,他说:“还可以。”在这里,你问他对这个朋友来说,是一个事件;“最近过得怎么样?”这个信息包含在事件中;朋友回答你的问题是这个事件的回调函数结果,基于事件的信息,他回答了“还可以”。
再举个现在的例子:我看到题主这道题,写下参考答案。题主看后无感。看到题主这道题对我来说是事件,写下参考答案是我对这个事件的回调函数结果,题主看到这个答案对题主是事件,无感是题主对此事件的回调函数结果。在题主写下这个问题后,每多一人看到此题,就触发了此人看到此题事件和浏览数+1事件,看到的人有些默默走过,是回调函数的运行结果之一;有些动笔写下答案,是另一种回调函数的运行结果。不同的人看到,触发了同一个事件,但每个人的回调函数不同,所以产生了不同的结果。从这里就可以看到从题主提问,到题主得到回答,整个过程都有事件贯穿其中,有些不可见,有些可见,充当着我们交流的媒介。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
事件,被动执行的函数。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
举个例子,如果你的大脑是浏览器,由于常年的加班让你觉得有必要提醒下老板加工资(产生需求)。当老板(对象)穿着阿迪达斯人字拖(属性)吃着火锅唱着歌(方法)走进办公室(条件判断,亦可理解为监听老板进来这一事件),你一把抄起海盗船钛金机械键盘给了他一耳光,把他人字拖扔了(监听器为true时所执行的动作,此例为操作对象)
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
事件应该就是用户主动的行为 必须要有某些东西改变
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
通俗点讲,举例:你推开了一个人,拿了一杯奶茶喝。这个“拿”与“推”,就是事件。
同步到新浪微博
分享到微博?
Hi,欢迎来到 SegmentFault 技术社区!⊙▽⊙ 在这里,你可以提出编程相关的疑惑,关注感兴趣的问题,对认可的回答投赞同票;大家会帮你解决编程的问题,和你探讨技术更新,为你的回答投上赞同票。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
扫扫下载 AppJavaScript 事件
事件一般是用于浏览器和用户操作进行交互。最早是 IE 和 Netscape Navigator 中出现 ,作为分担服务器端运算负载的一种手段。 直到几乎所有的浏览器都支持事件处理。
第1章 事件入门
Script 事件是由访问 Web 页面的用户引起的一系列操作,例如:用户点击。当用户执行某些操作的时候,再去执行一系列代码。
1.1事件介绍
事件一般是用于和用户操作进行交互。最早是 IE 和 Netscape Navigator 中出现 ,作为分担服务器端运算负载的一种手段。 直到几乎所有的浏览器都支持事件处理。 而 DOM2级规范开始尝试以一种复合逻辑的方式标准化 DOM 事件。IE9、Firefox、Opera、Safari 和Chrome 全都已经实现了“DOM2 级事件”模块的核心部分。IE8 之前浏览器仍然使用其专有事件模型。
1.2事件模型
有三种事件模型:内联模型、脚本模型和 DOM2 模型。
1.2.1内联模型
这种模型是最传统接单的一种处理事件的方法。 在内联模型中, 事件处理函数是 HTML标签的一个属性,用于处理指定事件。虽然内联在早期使用较多,但它是和 HTML 混写的 ,并没有与 HTML 分离。
//在 HTML 中把事件处理函数作为属性执行 JS 代码
//注意单双引号
//在 HTML 中把事件处理函数作为属性执行 JS 函数
//执行 JS 的函数
PS:函数不得放到 window.onload 里面,这样就看不见了。
1.2.2脚本模型
由于内联模型违反了 HTML 与 JavaScript 代码层次分离的原则。为了解决这个问题, 我们可以在 JavaScript 中处理事件。这种处理方式就是脚本模型。
var input = document.getElementsByTagName('input')[0]; //得到 input 对象
input.onclick = function () { //匿名函数执行
alert('Lee');
PS:通过匿名函数,可以直接触发对应的代码。也可以通过指定的函数名赋值的方式来执行函数(赋值的函数名不要跟着括号)。input.onclick = //把函数名赋值给事件处理函数
第2章 事件处理函数
JavaScript 可以处理的事件类型为:鼠标事件、键盘事件、HTML 事件。
JavaScript 事件处理函数及其使用列表
事件处理函数
影响的元素
当图像加载被中断时
窗口、框架、所有表单对象
当焦点从对象上移开时
输入框,选择框和文本区域
当改变一个元素的值且失去焦点时
链接、按钮、表单对象、图像映射区域
当用户单击对象时
ondblclick
链接、按钮、表单对象
当用户双击对象时
ondragdrop
当用户将一个对象拖放到浏览器窗口时
当脚本中发生语法错误时
窗口、框架、所有表单对象
当单击鼠标或者将鼠标移动聚焦到窗口或框架时
文档、图像、链接、表单
当按键被按下时
onkeypress
文档、图像、链接、表单
当按键被按下然后松开时
文档、图像、链接、表单
当按键被松开时
主题、框架集、图像
文档或图像加载后
主体、框架集
文档或框架集卸载后
当图标移除链接时
onmouseover
当鼠标移到链接时
当浏览器窗口移动时
表单复位按钮
单击表单的 reset 按钮
当选择一个表单对象时
当选择一个表单对象时
当发送表格到服务器时
PS:所有的事件处理函数都会都有两个部分组成,on + 事件名称,例如 click 事件的事件处理函数就是:onclick。在这里,我们主要谈论脚本模型的方式来构建事件,违反分离原则的内联模式,我们忽略掉。对于每一个事件,它都有自己的触发范围和方式,如果超出了触发范围和方式,事件处理将失效。
2.1鼠标事件,页面所有元素都可触发
1. click:当用户单击鼠标按钮或按下回车键时触发。
input.onclick = function () {
alert(&Lee&);
2. dblclick:当用户双击主鼠标按钮时触发。
input.ondblclick = function () {
alert(&Lee&);
3. mousedown:当用户按下了鼠标还未弹起时触发。
input.onmousedown = function () {
alert(&Lee&);
4. mouseup:当用户释放鼠标按钮时触发。
input.onmouseup = function () {
alert(&Lee&);
5. mouseover:当鼠标移到某个元素上方时触发。
input.onmouseover = function () {
alert(&Lee&);
6. mouseout:当鼠标移出某个元素上方时触发。
input.onmouseout = function () {
alert(&Lee&);
7. mousemove:当鼠标指针在元素上移动时触发。
input.onmousemove = function () {
alert(&Lee&);
2.2 键盘事件
1. keydown:当用户按下键盘上任意键触发,如果按住不放,会重复触发。
onkeydown = function () {
alert(&Lee&);
2. keypress:当用户按下键盘上的字符键触发,如果按住不放,会重复触发。
onkeypress = function () {
alert(&Lee&);
3. keyup:当用户释放键盘上的键触发。
onkeyup = function () {
alert(&Lee&);
2.3 HTML 事件
1. load:当页面完全加载后在 window 上面触发,或当框架集加载完毕后在框架集上触发。
window.onload = function () {
alert(&Lee&);
2. unload:当页面完全卸载后在 window 上面触发,或当框架集卸载后在框架集上触发。
window.onunload = function () {
alert(&Lee&);
3. select:当用户选择文本框(input 或 textarea)中的一个或多个字符触发。
input.onselect = function () {
alert(&Lee&);
4. change:当文本框(input 或 textarea)内容改变且失去焦点后触发。
input.onchange = function () {
alert(&Lee&);
5. focus:当页面或者元素获得焦点时在 window 及相关元素上面触发。
input.onfocus = function () {
alert(&Lee&);
6. blur:当页面或元素失去焦点时在 window 及相关元素上触发。
input.onblur = function () {
alert(&Lee&);
7. submit:当用户点击提交按钮在元素上触发。
form.onsubmit = function () {
alert(&Lee&);
8. reset:当用户点击重置按钮在元素上触发。
form.onreset= function () {
alert(&Lee&);
9. resize:当窗口或框架的大小变化时在 window 或框架上触发。
window.onresize = function () {
alert(&Lee&);
10. scroll:当用户滚动带滚动条的元素时触发。
window.onscroll = function () {
alert(&Lee&);
第3章 事件对象
JavaScript 事件的一个重要方面是它们拥有一些相对一致的特点,可以给你的开发提供更多的强大功能。 最方便和强大的就是事件对象, 他们可以帮你处理鼠标事件和键盘敲击方面的情况,此外还可以修改一般事件的捕获/冒泡流的函数。
3.1 事件对象
事件处理函数的一个标准特性是, 以某些方式访问的事件对象包含有关于当前事件的上下文信息。
事件处理三部分组成:对象.事件处理函数=函数。例如:单击文档任意处。
document.onclick = function () {
alert('Lee');
PS:以上程序的名词解释:click 表示一个事件类型,单击。onclick 表示一个事件处理函数或绑定对象的属性(或者叫事件监听器、侦听器)。document 表示一个绑定的对象,用于触发某个元素区域。function()匿名函数是被执行的函数,用于触发后执行。
除了用匿名函数的方法作为被执行的函数,也可以设置成独立的函数。
document.onclick = //直接赋值函数名即可,无须括号
function box() {
`alert('Lee');
this 关键字和上下文
在面向对象那章我们了解到:在一个对象里,由于作用域的关系,this 代表着离它最近对象。
var input = document.getElementsByTagName('input')[0];
input.onclick = function () {
alert(this.value); //HTMLInputElement,this 表示 input 对象
从上面的拆分,我们并没有发现本章的重点:事件对象。那么事件对象是什么?它在哪里呢?当触发某个事件时,会产生一个事件对象,这个对象包含着所有与事件有关的信息 。包括导致事件的元素、事件的类型、以及其它与特定事件相关的信息。
事件对象,我们一般称作为 event 对象,这个对象是浏览器通过函数把这个对象作为参数传递过来的。那么首先,我们就必须验证一下,在执行函数中没有传递参数,是否可以得到隐藏的参数。
function box() { //普通空参函数
alert(arguments.length); //0,没有得到任何传递的参数
input.onclick = function () { //事件绑定的执行函数
alert(arguments.length); //1,得到一个隐藏参数
通过上面两组函数中, 我们发现, 通过事件绑定的执行函数是可以得到一个隐藏参数的 。说明浏览器会自动分配一个参数,这个参数其实就是 event 对象。
input.onclick = function () {
alert(arguments[0]); //MouseEvent,鼠标事件对象
上面这种做法比较累,那么比较简单的做法是,直接通过接收参数来得到即可。
input.onclick = function (evt) { //接受 event 对象,名称不一定非要 event
alert(evt); //MouseEvent,鼠标事件对象
直接接收 event 对象,是 W3C 的做法,IE 不支持,IE 自己定义了一个 event 对象,直接在 window.event 获取即可。
input.onclick = function (evt) {
var e = evt || window. //实现跨浏览器兼容获取 event 对象
3.2鼠标事件对象
鼠标事件是 Web 上面最常用的一类事件,毕竟鼠标还是最主要的定位设备。那么通过事件对象可以获取到鼠标按钮信息和屏幕坐标获取等。
3.2.1 鼠标按钮
只有在主鼠标按钮被单击时(常规一般是鼠标左键)才会触发 click 事件,因此检测按钮的信息并不是必要的。但对于 mousedown 和 mouseup 事件来说,则在其 event 对象存在一个 button 属性,表示按下或释放按钮。
非 IE(W3C)中的 button 属性
表示主鼠标按钮(常规一般是鼠标左键)
表示中间的鼠标按钮(鼠标滚轮按钮)
表示次鼠标按钮(常规一般是鼠标右键)
IE 中的 button 属性
表示没有按下按钮
表示主鼠标按钮(常规一般是鼠标左键)
表示次鼠标按钮(常规一般是鼠标右键)
表示同时按下了主、次鼠标按钮
表示按下了中间的鼠标按钮
表示同时按下了主鼠标按钮和中间的鼠标按钮
表示同时按下了次鼠标按钮和中间的鼠标按钮
表示同时按下了三个鼠标按钮
PS:在绝大部分情况下,我们最多只使用主次中三个单击键,IE 给出的其他组合键一般无法使用上。所以,我们只需要做上这三种兼容即可。
function getButton(evt) { //跨浏览器左中右键单击相应
var e = evt || window.
if (evt) { //Chrome 浏览器支持 W3C 和 IE
return e. //要注意判断顺序
} else if (window.event) {
switch(e.button) {
document.onmouseup = function (evt) { //调用
if (getButton(evt) == 0) {
alert('按下了左键!');
} else if (getButton(evt) == 1) {
alert('按下了中键!');
} else if (getButton(evt) == 2) {
alert('按下了右键!' );
3.2.2 可视区及屏幕坐标
事件对象提供了两组来获取浏览器坐标的属性, 一组是页面可视区左边, 另一组是屏幕坐标。
可视区 X 坐标,距离左边框的位置
可视区 Y 坐标,距离上边框的位置
屏幕区 X 坐标,距离左屏幕的位置
屏幕区 Y 坐标,距离上屏幕的位置
document.onclick = function (evt) {
var e = evt || window.
alert(e.clientX + ',' + e.clientY);
alert(e.screenX + ',' + e.screenY);
3.2.3 修改键
有时,我们需要通过键盘上的某些键来配合鼠标来触发一些特殊的事件。这些键为:
Shfit、Ctrl、Alt 和 Meat(Windows 中就是 Windows 键,苹果机中是 Cmd 键),它们经常被用来修改鼠标事件和行为,所以叫修改键。
修改键属性
判断是否按下了 Shfit 键
判断是否按下了 ctrlKey 键
判断是否按下了 alt 键
判断是否按下了 windows 键,IE 不支持
function getKey(evt) {
var e = evt || window.
var keys = [];
if (e.shiftKey) keys.push('shift'); //给数组添加元素
if (e.ctrlKey) keys.push('ctrl');
if (e.altKey) keys.push('alt');
document.onclick = function (evt) {
alert(getKey(evt));
4.3键盘事件对象
用户在使用键盘时会触发键盘事件。 “DOM2 级事件”最初规定了键盘事件,结果又删除了相应的内容。最终还是使用最初的键盘事件,不过 IE9 已经率先支持“DOM3”级键盘事件。
4.3.1 键码
在发生 keydown 和 keyup 事件时,event 对象的 keyCode 属性中会包含一个代码,与键盘上一个特定的键对应。对数字字母字符集,keyCode 属性的值与 ASCII 码中对应小写字母或数字的编码相同。字母中大小写不影响。
document.onkeydown = function (evt) {
alert(evt.keyCode); //按任意键,得到相应的 keyCode
不同的浏览器在 keydown 和 keyup 事件中,会有一些特殊的情况:
在 Firefox 和 Opera 中,分号键时 keyCode 值为 59,也就是 ASCII 中分号的编码;而 IE和 Safari 返回 186,即键盘中按键的键码。
PS:其他一些特殊情况由于浏览器版本太老和市场份额太低,这里不做补充。
4.3.2字符编码
Firefox、Chrome 和 Safari 的 event 对象都支持一个 charCode 属性,这个属性只有在发生 keypress 事件时才包含值,而且这个值是按下的那个键所代表字符的 ASCII 编码。此时的 keyCode 通常等于 0 或者也可能等于所按键的编码。IE 和 Opera 则是在 keyCode 中保存字符的 ASCII 编码。
function getCharCode(evt) {
var e = evt || window.
if (typeof e.charCode == 'number') {
return e.charC
return e.keyC
PS:可以使用 String.fromCharCode()将 ASCII 编码转换成实际的字符。
keyCode 和 charCode 区别如下:比如当按下“a 键(重视是小写的字母)时,
在 Firefox 中会获得
keydown: keyCode is 65 charCode is 0
keyup: keyCode is 65 charCode is 0
keypress: keyCode is 0 charCode is 97
在 IE 中会获得
keydown: keyCode is 65 charCode is undefined
keyup: keyCode is 65 charCode is undefined
keypress: keyCode is 97 charCode is undefined
而当按下 shift 键时,在 Firefox 中会获得
keydown:keyCode is 16 charCode is 0
keyup: keyCode is 16 charCode is 0
在 IE 中会获得
keydown:keyCode is 16 charCode is undefined
keyup: keyCode is 16 charCode is undefined
keypress:不会获得任何的 charCode 值,因为按 shift 并没输入任何的字符,并且也不会触发 keypress 事务
PS:在 keydown 事务里面,事务包含了 keyCode & 用户按下的按键的物理编码。
在 keypress 里,keyCode 包含了字符编码,即默示字符的 ASCII 码。如许的情势实用于所有的浏览器 & 除了火狐,它在 keypress 事务中的 keyCode 返回值为 0。
4.4 W3C与 IE
在标准的 DOM 事件中,event 对象包含与创建它的特定事件有关的属性和方法。触发的事件类型不一样,可用的属性和方法也不一样。
W3C 中 event 对象的属性和方法
表明事件是否冒泡
cancelable
表明是否可以取消事件的默认行为
currentTarget
其事件处理程序当前正在处理事件的那个元素
与事件相关的细节信息
eventPhase
调用事件处理程序的阶段:1 表示捕获阶段,2 表示“处理目标” ,3 表示冒泡阶段
preventDefault()
取消事件的默认行为。 如cancelabel是 true,则可以使用这个方法
stopPropagation()
取消事件的进一步捕获或冒泡。如果bubbles 为 true, 则可以使用这个方法
事件的目标
被触发的事件的类型
AbstractView
与事件关联的抽象视图。等同于发生事件的 window 对象
IE 中 event 对象的属性
cancelBubble
默认值为 false,但将其设置为 true 就可以取消事件冒泡
returnValue
默认值为 true, 但将其设置为 false 就可以取消事件的默认行为
srcElement
事件的目标
被触发的事件类型
W3C 中的 target 和 IE 中的 srcElement
在这里,我们只看所有浏览器都兼容的属性或方法。首先第一个我们了解一下 W3C 中的 target 和 IE 中的 srcElement,都表示事件的目标。
function getTarget(evt) {
var e = evt || window.
return e.target || e.srcE //兼容得到事件目标 DOM 对象
document.onclick = function (evt) {
var target = getTarget(evt);
alert(target);
事件流是描述的从页面接受事件的顺序,当几个都具有事件的元素层叠在一起的时候 ,那么你点击其中一个元素, 并不是只有当前被点击的元素会触发事件, 而层叠在你点击范围的所有元素都会触发事件。事件流包括两种模式:冒泡和捕获。
是从里往外逐个触发。事件捕获,是从外往里逐个触发。那么现代的浏览器默认情况下都是冒泡模型,而捕获模式则是早期的 Netscape 默认情况。而现在的浏览器要使用 DOM2 级模型的事件绑定机制才能手动定义事件流模式。
document.onclick = function () {
alert('我是 document');
document.documentElement.onclick = function () {
alert('我是 html');
document.body.onclick = function () {
alert('我是 body');
document.getElementById('box').onclick = function () {
alert('我是 div');
document.getElementsByTagName('input')[0].onclick = function () {
alert('我是 input');
PS::在阻止冒泡的过程中,W3C 和 IE 采用的不同的方法,那么我们必须做一下兼容。
function stopPro(evt) {
var e = evt || window.
window.event ? e.cancelBubble = true : e.stopPropagation();
第4章 事件绑定及深入
事件绑定分为两种:
传统事件绑定(内联模型,脚本模型), 现代事件绑定
(DOM2 级模型)。现代事件绑定在传统绑定上提供了更强大更方便的功能。
4.1 传统事件绑定的问题
传统事件绑定有内联模型和脚本模型,内联模型我们不做讨论,基本很少去用。先来看一下脚本模型,脚本模型将一个函数赋值给一个事件处理函数。
var box = document.getElementById('box'); //获取元素
box.onclick = function () { //元素点击触发事件
alert('Lee');
问题一:一个事件处理函数触发两次事件
window.onload = function () { //第一组程序项目或第一个 JS 文件
alert(&Lee&);
window.onload = function () { //第二组程序项目或第二个 JS 文件
alert(&Mr.Lee&);
当两组程序或两个 JS 文件同时执行的时候,后面一个会把前面一个完全覆盖掉。导致前面的 window.onload 完全失效了。
解决覆盖问题,我们可以这样去解决:
window.onload = function () { //第一个要执行的事件,会被覆盖
alert('Lee');
if (typeof window.onload == 'function') { //判断之前是否有 window.onload
var saved = //创建一个保存器
saved = window. //把之前的 window.onload 保存起来
window.onload = function () { //最终一个要执行事件
if (saved) saved(); //执行之前一个事件
alert('Mr.Lee'); //执行本事件的代码
问题二:事件切换器
box.onclick = toB //第一次执行 toBlue()
function toRed() {
this.className = 'red';
this.onclick = toB //第三次执行 toBlue(),然后来回切换
function toBlue() {
this.className = 'blue';
this.onclick = toR //第二次执行 toRed()
这个切换器在扩展的时候,会出现一些问题:
如果增加一个执行函数,那么会被覆盖
box.onclick = toA //被增加的函数
box.onclick = toB //toAlert 被覆盖了 如果解决覆盖问题,就必须包含同时执行,但又出新问题
box.onclick = function () { //包含进去,但可读性降低
toAlert(); //第一次不会被覆盖,但第二次又被覆盖
toBlue.call(this); //还必须把 this 传递到切换器里
综上的三个问题:覆盖问题、可读性问题、this 传递问题。我们来创建一个自定义的事件处理函数,来解决以上三个问题。
function addEvent(obj, type, fn) { //取代传统事件处理函数
var saved = //保存每次触发的事件处理函数
if (typeof obj['on' + type] == 'function') { //判断事件是否存在
saved = obj['on' + type]; //如果有,保存上一个事件
obj['on' + type] = function () { //然后执行
if (saved) saved(); //执行上一个
fn.call(this); //执行函数,把 this 传递过去
addEvent(window, 'load', function () { //执行到了
alert('Lee');
addEvent(window, 'load', function () { //执行到了
alert('Mr.Lee');
PS:以上编写的自定义事件处理函数,还有一个问题没有处理,就是两个相同函数名的函数误注册了两次或多次,那么应该把多余的屏蔽掉。那我们就需要把事件处理函数进行遍历,如果有同样名称的函数名就不添加即可。(这里就不做了)
addEvent(window, 'load', init); //注册第一次
addEvent(window, 'load', init); //注册第二次,应该忽略
function init() {
alert('Lee');
用自定义事件函数注册到切换器上查看效果:
addEvent(window, 'load', function () {
var box = document.getElementById('box');
addEvent(box, 'click', toBlue);
function toRed() {
this.className = 'red';
addEvent(this, 'click', toBlue);
function toBlue() {
this.className = 'blue';
addEvent(this, 'click', toRed);
PS:当你单击很多很多次切换后,浏览器直接卡死,或者弹出一个错误:too much recursion(太多的递归)。主要的原因是,每次切换事件的时候,都保存下来,没有把无用的移除,导致越积越多,最后卡死。
function removeEvent(obj, type) {
if (obj['on'] + type) obj['on' + type] = //删除事件处理函数
以上的删除事件处理函数只不过是一刀切的删除了, 这样虽然解决了卡死和太多递归的问题。但其他的事件处理函数也一并被删除了,导致最后得不到自己想要的结果。如果想要只删除指定的函数中的事件处理函数,那就需要遍历,查找。(这里就不做了)
4.2 W3C事件处理函数
“DOM2 级事件”定义了两个方法,用于添加事件和删除事件处理程序的操作:addEventListener()和 removeEventListener()。
所有 DOM 节点中都包含这两个方法,并且它们都接受 3 个参数:事件名、函数、冒泡或捕获的布尔值(true 表示捕获,false 表示冒泡)。
window.addEventListener('load', function () {
alert('Lee');
}, false);
window.addEventListener('load', function () {
alert('Mr.Lee');
}, false);
PS:W3C 的现代事件绑定比我们自定义的好处就是:
可以解决覆盖事件绑定; 可以屏蔽相同的函数; 可以设置冒泡和捕获。
window.addEventListener('load', init, false); //第一次执行了
window.addEventListener('load', init, false); //第二次被屏蔽了
function init() {
alert('Lee');
事件切换器
window.addEventListener('load', function () {
var box = document.getElementById('box');
box.addEventListener('click', function () { //不会被误删
alert('Lee');
}, false);
box.addEventListener('click', toBlue, false); //引入切换也不会太多递归卡死
}, false);
function toRed() {
this.className = 'red';
this.removeEventListener('click', toRed, false);
this.addEventListener('click', toBlue, false);
function toBlue() {
this.className = 'blue';
this.removeEventListener('click', toBlue, false);
this.addEventListener('click', toRed, false);
设置冒泡和捕获阶段
之前我们上一章了解了事件冒泡,即从里到外触发。我们也可以通过 event 对象来阻止某一阶段的冒泡。那么 W3C 现代事件绑定可以设置冒泡和捕获。
document.addEventListener('click', function () {
alert('document');
}, true); //把布尔值设置成 true,则为捕获
box.addEventListener('click', function () {
alert('Lee');
}, true); //把布尔值设置成 false,则为冒泡
综上所述,W3C是比较完美的解决了事件绑定中的一些问题,但是IE8即以前的版本并不支持,而是采用了自己的事件绑定处理,当然IE9已经完全支持了
4.3 IE事件处理函数
IE 实现了与 DOM 中类似的两个方法:attachEvent()和 detachEvent()。、这两个方法接受相同的参数:事件名称和函数。
在使用这两组函数的时候,先把区别说一下:
IE 不支持捕获,只支持冒泡; IE 添加事件不能屏蔽重复的函数; IE 中的 this 指向的是 window 而不是 DOM 对象。 在传统事件上,IE 是无法接受到 event 对象的,但使用了 attchEvent()却可以,但有些区别。
window.attachEvent('onload', function () {
var box = document.getElementById('box');
box.attachEvent('onclick', toBlue);
function toRed() {
var that = window.event.srcE
that.className = 'red';
that.detachEvent('onclick', toRed);
that.attachEvent('onclick', toBlue);
function toBlue() {
var that = window.event.srcE
that.className = 'blue';
that.detachEvent('onclick', toBlue);
that.attachEvent('onclick', toRed);
PS:IE 不支持捕获,无解。IE 不能屏蔽,需要单独扩展或者自定义事件处理。IE 不能传递 this,可以 call 过去。
window.attachEvent('onload', function () {
var box = document.getElementById('box');
box.attachEvent('onclick', function () {
alert(this === window); //this 指向的 window
window.attachEvent('onload', function () {
var box = document.getElementById('box');
box.attachEvent('onclick', function () {
toBlue.call(box); //把 this 直接 call 过去
function toThis() {
alert(this.tagName);
在传统绑定上,IE 是无法像 W3C 那样通过传参接受 event 对象,但如果使用了attachEvent()却可以。
box.onclick = function (evt) {
alert(evt); //undefined
box.attachEvent('onclick', function (evt) {
alert(evt); //object
alert(evt.type); //click
box.attachEvent('onclick', function (evt) {
alert(evt.srcElement === box); //true
alert(window.event.srcElement === box); //true
最后,为了让 IE 和 W3C 可以兼容这个事件切换器,我们可以写成如下方式:
function addEvent(obj, type, fn) { //添加事件兼容
if (obj.addEventListener) {
obj.addEventListener(type, fn);
} else if (obj.attachEvent) {
obj.attachEvent('on' + type, fn);
function removeEvent(obj, type, fn) { //移除事件兼容
if (obj.removeEventListener) {
obj.removeEventListener(type, fn);
} else if (obj.detachEvent) {
obj.detachEvent('on' + type, fn);
function getTarget(evt) { //得到事件目标
if (evt.target) {
return evt.
} else if (window.event.srcElement) {
return window.event.srcE
PS:调用忽略,IE 兼容的事件,如果要传递 this,改成 call 即可。
PS:IE 中的事件绑定函数 attachEvent()和 detachEvent()可能在实践中不去使用,有几个原因:
IE9 就将全面支持 W3C 中的事件绑定函数; IE的事件绑定无法传递 IE的事件绑定函数不支持捕获; 同一个函数注册绑定后,没有屏蔽掉; 有内存泄漏的问题 。
至于怎么替代,我们将在以后的项目课程中探讨。
4.4 事件对象的其他补充
4.4.1relatedTarget,,fromElement,toElement
在 W3C 提供了一个属性:relatedTarget;这个属性可以在 mouseover 和 mouseout 事件中获取从哪里移入和从哪里移出的 DOM 对象。
box.onmouseover = function (evt) { //鼠标移入 box
alert(evt.relatedTarget); //获取移入 box 最近的那个元素对象
box.onmouseout = function (evt) { //鼠标移出 box
alert(evt.relatedTarget); //获取移出 box 最近的那个元素对象
IE 提供了两组分别用于移入移出的属性: fromElement 和 toElement, 分别对应 mouseover和 mouseout。
box.onmouseover = function (evt) { //鼠标移入 box
alert(window.event.fromElement.tagName); //获取移入 box 最近的那个元素对象 span
box.onmouseout = function (evt) { //鼠标移入 box
alert(window.event.toElement.tagName); //获取移入 box 最近的那个元素对象 span
PS:fromElement 和 toElement 如果分别对应相反的鼠标事件,没有任何意义。
剩下要做的就是跨浏览器兼容操作:
function getTarget(evt) {
var e = evt || window. //得到事件对象
if (e.srcElement) { //如果支持 srcElement,表示 IE
if (e.type == 'mouseover') { //如果是 over
return e.fromE //就使用 from
} else if (e.type == 'mouseout') { //如果是 out
return e.toE //就使用 to
} else if (e.relatedTarget) { //如果支持 relatedTarget,表示 W3C
return e.relatedT
4.4.2阻止事件的默认行为
有时我们需要阻止事件的默认行为, 比如: 一个超链接的默认行为就点击然后跳转到指定的页面。那么阻止默认行为就可以屏蔽跳转的这种操作,而实现自定义操作。
取消事件默认行为还有一种不规范的做法,就是返回 false。
link.onclick = function () {
alert('Lee');
//直接给个假,就不会跳转了。
PS:虽然 return false;可以实现这个功能,但有;
必须写到最后,这样导致中间的代码执行后,有可能执行不到 return false; return false 写到最前那么之后的自定义操作就失效了。所以,最好的方法应该是在最前面就阻止默认行为,并且后面还能执行代码。
//W3C,阻止默认行为
link.onclick = function (evt) {
evt.preventDefault();
alert('Lee');
//IE,阻止默认行为
link.onclick = function (evt) {
window.event.returnValue =
alert('Lee');
//跨浏览器兼容
function preDef(evt) {
var e = evt || window.
if (e.preventDefault) {
e.preventDefault();
e.returnValue =
4.4.3contextmenu
上下文菜单事件:contextmenu,当我们右击网页的时候,会自动出现 windows 自带的菜单。那么我们可以使用 contextmenu 事件来修改我们指定的菜单,但前提是把右击的默认行为取消掉。
addEvent(window, 'load', function () {
var text = document.getElementById('text');
addEvent(text, 'contextmenu', function (evt) {
var e = evt || window.
preDef(e);
var menu = document.getElementById('menu');
menu.style.left = e.clientX + 'px';
menu.style.top = e.clientY + 'px';
menu.style.visibility = 'visible';
addEvent(document, 'click', function () {
document.getElementById('myMenu').style.visibility = 'hidden';
PS:contextmenu 事件很常用,这直接导致浏览器兼容性较为稳定。
4.4.4beforeunload
卸载前事件:beforeunload,这个事件可以帮助在离开本页的时候给出相应的提示, “离开”或者“返回”操作。
addEvent(window, 'beforeunload', function (evt) {
preDef(evt);
4.4.5mousewheel和DOMMouseScroll
鼠标滚轮(mousewheel)和 DOMMouseScroll,用于获取鼠标上下滚轮的距离。
addEvent(document, 'mousewheel', function (evt) { //非火狐
alert(getWD(evt));
addEvent(document, 'DOMMouseScroll', function (evt) { //火狐
alert(getWD(evt));
function getWD(evt) {
var e = evt || window.
if (e.wheelDelta) {
return e.wheelD
} else if (e.detail) {
return -evt.detail * 30; //保持计算的统一
PS:通过浏览器检测可以确定火狐只执行 DOMMouseScroll。}

我要回帖

更多关于 jq鼠标经过离开事件 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信