JavaScript—事件
事件机制:
在用户使用键盘、鼠标等设备进行操作时,实际上每一次的操作都是在发起一个事件。
当我们的鼠标点击到窗口上的按钮时,并不是鼠标的箭头真正点击到这个按钮了,而是鼠标发出了一个动作事件,然后这个事件先被传送到了操作系统的命令处理带,然后再传送到负责显示图形的图像数据层,事件到这里后图像数据层会先看哪个程序的窗口在最上面(因为不是在最上面就没必要看了),再根据鼠标提供的X Y坐标确认点击的是哪个窗口上的按钮,接着再确认这个窗口是哪个程序。
确认完毕后,图像数据层就会将这个动作事件提交给相对应的执行程序,执行程序里的代码先寻找是哪个位置的数据哪个对象提供的,进行一系列的搜索,找到后这个对象就会执行相对应的代码,然后再将执行后的显示传送到图像数据中心进行显示。我们就会看到鼠标点击到了这个按钮。
之所以平时使用的时候没感觉出来,是因为这一系列的复杂的机制都是在瞬间完成的,只有在电脑卡顿的情况下才能感觉到点击后要等一段时间才会做出相应的响应。
示意图:
事件委托:
这其中有一个事件委托的概念,我们需要在代码中把事件委托也可以说是注册到按钮上,这时会有一个监听器监听着这个按钮,当用户点击按钮时就会去调用委托事件中的代码,这些代码都写在函数中。
所以简单来说,就是把一个写好的函数通过事件委托到按钮上,当用户点击按钮后,就会调用那个函数,函数里的代码就会执行。
例如:我把一段打印Hello World的函数,通过事件委托到按钮上,当我点击这个按钮的时候就会调用这个函数,函数执行完之后就会打印Hello World。
以上提到的事件只是众多事件类型中的一种点击事件,事件是有很多种类型的,例如:鼠标的单击、双击、滚轴,键盘的按键弹起、按下、长按等等,反正很多就是了,还有一些是某些元素特有的事件。
在介绍如何委托事件前,先介绍一下如何控制元素对象(标签对象),因为有些委托事件的方式需要去获得元素对象来进行事件的委托:
第一种获得方式是通过id去获得,这种方式需要用document对象去调用getElementById函数并传递元素的id值,就可以获得该id值的元素对象。
代码示例:
运行结果:
从审查元素中可以看到id值为test_sbutton的元素中的value值,为我js代码里设置的值。
错误示例:
因为代码是是从上至下解析的,如果你要获得body里面的元素对象,却把script写在了body前面,所以当执行js里面获得元素对象的代码时就会报错:
代码示例:
运行结果:
第二种方式是直接使用id值,可以直接拿id值去定义该元素对象里面的属性值:
代码示例:
运行结果:
以上只是介绍比较常见的两种获得元素对象的方式,除此之外还有很多种获得方式,可以参考以下文章:
http://www.jb51.net/article/64874.htm
注意:id值不要设置重复的最好保持唯一性,如果设置重复的话,js就不能直接获得元素对象,而是会获得一个对象数组,如果遇到id值重复的情况下,就得遍历数组去获得对象:
代码示例:
运行结果:
思维导图:
接下来开始介绍JavaScript中给元素委托事件的三种常用的方式:
第一种方式,写好函数代码后,通过元素中的事件属性进行委托,下面用鼠标事件中的mouseout和mouseover事件进行演示,mousseout事件在鼠标移动出该元素时会触发,mouseover事件在鼠标移动进该元素时会触发,属于焦点类的事件:
代码示例:
运行结果:
当鼠标的光标移动进按钮时会触发mouseover事件,移动出按钮时会触发mousseout事件,然后就会调用委托到事件中的函数代码,函数被调用执行就会在控制台中输出这些信息。
所谓焦点就是鼠标的光标的位置,例如当你在文本框输入文字时需要点击一下文本框才能输入,这就是要让文本框获得鼠标焦点。
第二种方式,通过id获取元素对象,然后通过该对象调用事件属性,使用函数表达式的方式把函数委托给事件:
代码示例:
运行结果:
除了函数表达式外也可以使用函数声明的方式,把函数的名称赋值给元素对象的事件属性,注意不能写上():
代码示例:
运行结果:
第三种方式,通过addEventListener函数添加一个事件监听器,需要传递事件的名称,和函数对象,函数对象可以是函数的名称,也可以是直接写一个函数上去:
代码示例:
运行结果:
同一个元素对象的同一个事件,可以添加多个函数,这些函数可以执行不同的内容,例如我在一个button元素的mouseover事件中分别添加了三个函数,这三个函数各自打印了一句话,那么当我鼠标碰到按钮时,就会打印出三句话:
代码示例:
运行结果:
addEventListener函数还有一个布尔参数,这个参数定义着父元素和子元素重叠并且都有委托事件的情况时,是先触发父元素的事件还是先触发子元素的事件,参数值为true是定义先触发父元素的事件,参数值为false则是定义先触发子元素的事件,不定义这个参数的话,默认情况下是先触发子元素的事件。
父元素和子元素重叠情况,不定义addEventListener函数布尔值的代码示例:
运行结果:
父元素和子元素重叠情况,定义addEventListener函数布尔值为true的代码示例:
运行结果:
还有一种情况就是父元素和子元素不完全重叠,这种情况下不定义addEventListener函数的布尔值,当鼠标移动到子元素时先触发父元素的事件,然后移出子元素时先触发子元素的事件再触发父元素的事件,这是因为默认情况下子元素的事件先执行,所以父元素的事件不会连续执行。
定义addEventListener函数的布尔值为true的话,当鼠标移动到子元素时先触发父元素的事件,然后移出子元素时还是触发父元素的事件,最后才触发子元素的事件,这是因为布尔值为true的情况下父元素的事件先执行,所以父元素的事件会连续执行。
父元素和子元素不完全重叠的情况,不定义addEventListener函数布尔值的代码示例:
运行结果:
父元素的事件不会连续执行
父元素和子元素不完全重叠的情况,定义addEventListener函数布尔值为true的代码示例:
运行结果:
父元素的事件会连续执行
事件源 Even:
事件源,就是事件产生时的信息收集,可以通过事件源对象获得很多相关数据,可以设置元素的属性,以下是常见的事件源对象属性:
通过事件源对象调用target属性设置元素的背景颜色代码示例:
运行结果:
以上只使用到了鼠标事件中的mouseout和mouseover事件,事件还有很多,以下是常见事件的分类思维导图: