1.何谓事件
用户和网页交互时的行为,动作,称之为事件;
2.监视事件
现实生活中,为了监视车辆是否违章,通过在红绿灯安装摄像头监视车辆,我们在网页中要想知道用户是否某个行为是否发生了,也需要安装监听器进行监视,这样当用户的行为发生时,我们要做相应的处理,从而提升用户体验.
我们监视用户的行为(事件)是否发生了,有3种方式:
(1)将事件监听器绑定在html标签上,作为标签属性存在
例如我们监听用户点击的行为,可采取这种写法<a href="onclick">
,通过on关键字加监视的行为(事件),这种方式由于html标签和javascript代码紧密耦合在一块,这样不是非常的灵活;
(2)DOM0级事件监听
将事件监听器绑定在DOM节点对象上
(3)DOM2级事件监听
DOM2级事件定义了两个方法用于处理指定和删除事件处理程序的操作:
- addEventListener
- removeEventListener
所有的DOM节点都包含这两个方法,并且它们都接受三个参数: - 事件类型
- 事件处理方法
- 布尔参数,如果是true表示在捕获阶段调用事件处理程序,如果是false,则是在事件冒泡阶段处理
//参数1:事件类型 click,没有on
//参数2:事件发生时执行的函数
//参数3:是否捕获,true捕获、false非捕获-事件冒泡(100%----false)
- IE(6-7-8)等浏览器通过attachEvent方法进行监听,通过detachEvent来移除监听程序
在这里需要特别注意的是IE浏览器只支持事件冒泡的事件流,添加的事件处理程序发生在事件冒泡阶段;
参数1:事件类型:加上on关键字
参数2:事件发生时执行的函数
将上述代码进行简单的封装,保存到common.js文件中,之后导入主文件中进行调用
封装如下:
3.事件流
事件流描述的是从页面中接收事件的顺序,比如有两个嵌套的div,点击了内层的div,这时候是内层的div先触发click事件还是外层先触发?目前主要有三种模型:
(1) IE的事件冒泡:事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的元素
(2) Netscape的事件捕获:不太具体的节点更早接收事件,而最具体的元素最后接收事件,和事件冒泡相反
(3) DOM事件流:DOM2级事件规定事件流包括三个阶段,事件捕获阶段,处于目标阶段,事件冒泡阶段,首先发生的是事件捕获,为截取事件提供机会,然后是实际目标接收事件,最后是冒泡阶段
采用以下实例来说明这种事件关系:
4.事件捕获和事件冒泡
事件捕获:先执行父元素身上的事件,再执行自身.设置为true;
事件冒泡:先执行自己身上的事件,再执行父元素身上的.设置false;
阻止事件冒泡:
通过事件对象阻止,事件对象是当事件(用户行为)发生的时候,会自动产生的一个对象,而且这个对象会自动传递到函数里面,通常我们会通过事件对象来获得当行为发生时,事件主题的信息(坐标、左击、右击等)
分别将执行事件的stopPropogation方法和将cancleBubble属性设置为true,可以阻止主流浏览器和IE浏览器的事件冒泡现象;
- event.stopPropogation()
- event.cancleBubble = true
5.事件对象
DOM中的事件对象
在触发DOM上的某个事件的时候会产生一个事件对象event,这个对象包含着所有与事件有关的信息,包括产生事件的元素、事件类型等相关信息。所有浏览器都支持event对象,但支持方式不同。
event对象包含与创建它的特定事件有关的属性和方法,触发事件的类型不同,可用的属性和方法也不同,但是所有事件都会包含
6.事件分类
(1)鼠标事件:用户鼠标的行为
- click :鼠标单击事件
- dbclick:鼠标双击行为(连续点击)
- mousedown:鼠标按下行为
- mouseup:鼠标抬起行为
通常应用场景:鼠标按下的时候,获得是左击还是右击?通过事件对象的button属性来获得:- button属性为:0表示鼠标左击
- button属性为:1表示滑轮按下
- button属性为:2表示鼠标右击
- mouseover:鼠标移入(会出现事件冒泡,不仅执行子元素上的事件,而且还会执行父元素上的事件)
- mouseout:鼠标移除(会出现事件冒泡,不仅执行子元素上的事件,而且还会执行父元素上的事件)
- mouseenter,mouseleave:鼠标移入,移出的行为(阻止事件冒泡)
要注意这两个鼠标移入移出事件与mouseover以及mouseout事件的区别在于是否阻止了事件冒泡机制;
如上图,可见当鼠标移入子元素的时候,发生了事件冒泡现象,父元素的事件监听也执行了;
如上图,可见当鼠标移入子元素的时候,只会执行子元素上的事件监听程序,而不会发生事件冒泡现象
- mousemove:鼠标移动(放大镜)
通常通过鼠标移动的时候,获得事件发生时鼠标所在的位置
通过事件对象的
clientX、clientY:获得距离客户端(浏览器)的距离(不包含滚动条卷去的高度)
pageX、pageY:获得距离页面的距离(包含滚动条卷去的高度)
- scroll:鼠标滑轮滚动行为
说明:由于scroll监视的是body整体在滑动,所以事件应该监视在body身上去
获得每次滑轮滚动时,滚动的距离,通过scrollTop获得滚动距离,而scrollHeight获得滚动条总的高度;- scrollTop:获得滚动条每次滚动的距离(距离顶部的距离)
- scrollLeft:获得滚动条每次滚动的距离(距离左边的距离)
- scrollHeight:获得滚动条总的高度
(2)键盘事件:用户键盘行为
说明:监视用户的键盘的行为,用户可以通过键盘和网页进行交互
javascript设计者给每一个按键分配了一个ASCII码,通过事件对象的keyCode属性获得这个ASCII码:
比如当我们按下w键时,对应的ASCLL码值为87,同理s键对应的是83.a键对应的是65,d键对应的是68;
有3个按键是特殊:
ctrl键 ----------- event.ctrlKey属性
shift键---------- event.shiftKey属性
alt键----------- event.altKey属性
这三个按键只有当我们按下的时候,对应的这3个属性才为true
将来我们只需要判断只要ctrlKey属性为true,说明ctrl键被按下了,只要altKey属性为true,说明altKey属性被按下了
- keydown:键盘按键按下
- keyup:键盘按键抬起
(3)表单事件
submit:表单提交事件(表单提交行为)
通常监视这个提交的行为,一旦提交行为发生了,我们要去验证输入框的内容是否合法,如果不符合规则,则阻止表单提交到服务器;select:输入框内容被选中行为
focus:输入框获得光标,获得焦点行为
blur:输入框失去光标,失去焦点行为
change:监视下拉列表内容发生变化行为
reset:重置按钮被点击的行为
(4)页面加载完毕事件
load:某个网页以及图像被完整加载
复习部分
题目1: DOM0 事件和DOM2级在事件监听使用方式上有什么区别?
DOM0级事件和DOM2级在时间监听使用方式的区别在于:
DOM0级事件
是将事件监听器绑定在DOM节点上,事件处理程序是被认为是当前绑定节点元素的事件处理属性的值,事件处理程序是在元素的作用域下运行,this指的是当前的元素;要注意的是一个事件只能绑定一次,如果绑定了新方法,则新方法会覆盖旧方法;DOM2级事件 定义了addEventListener,removeEventLIstener两种方法用于处理指定和删除事件处理程序的操作;所有的DOM节点都包含这两个方法,并且它们都接受三个参数:事件类型、事件处理方法、布尔参数。本质是通过DOM节点特定的绑定事件监听程序来进行事件处理;
题目2: attachEvent与addEventListener的区别?
attachEvent与addEventListener的区别在于:
兼容性上的区别,attachEvent是老版本IE上绑定事件处理程序的方法,而addEventListener是主流浏览器上的绑定事件处理程序的方法;
参数个数不相同,addEventListener有三个参数,attachEvent只有两个,attachEvent添加的事件处理程序只能发生在冒泡阶段,addEventListener第三个参数可以决定添加的事件处理程序是在捕获阶段还是冒泡阶段处理(我们一般为了浏览器兼容性都设置为冒泡阶段)
第一个参数意义不同,addEventListener第一个参数是事件类型(比如click,load),而attachEvent第一个参数指明的是事件处理函数名称(onclick,onload)
事件处理程序的作用域不相同,addEventListener的作用域是元素本身,this是指的触发元素,而attachEvent事件处理程序会在全局变量内运行,this是window,所以会返回undefined,而不是元素id。
为一个事件添加多个事件处理程序时,执行的顺序不同。 addEventListener 会按照添加的顺序执行。 attachEvent 添加多个事件处理程序时,顺序是无规律的。
题目3: 解释IE事件冒泡和DOM2事件传播机制?
事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的元素;
假如将DOM节点各级都绑定了事件监听器,那么当发生IE事件冒泡时,会从子类元素的事件处理程序开始执行,一级一级向上执行各级的事件冒泡程序;DOM2级事件规定事件流包括三个阶段,事件捕获阶段,处于目标阶段,事件冒泡阶段,首先发生的是事件捕获,为截取事件提供机会,然后是实际目标接收事件,最后是冒泡阶段;
题目4:如何阻止事件冒泡? 如何阻止默认事件?
要阻止事件的默认行为,可以使用preventDefault()方法,前提是cancelable值为true
stopPropagation()方法可以停止事件在DOM层次的传播,即取消进一步的事件捕获或冒泡
而要阻止在IE上的事件冒泡发生,则可将事件对象的cancleBubble 属性设置为true;
题目5:有如下代码,要求当点击每一个元素li时控制台展示该元素的文本内容。不考虑兼容
<script>
var liArr = document.getElementsByClassName('ct')[0].getElementsByTagName('li')
for(var i=0;i<liArr.length;i++){
liArr[i].addEventListener('click', function(){
console.log(this.innerText);
}, false)
}
</script>
题目6: 补全代码,要求:
- 当点击按钮开头添加时在<li>这里是</li>元素前添加一个新元素,内容为用户输入的非空字符串;当点击结尾添加时在最后一个 li 元素后添加用户输入的非空字符串.
- 当点击每一个元素li时控制台展示该元素的文本内容。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<ul class="ct">
<li>测试数据1</li>
<li>测试数据2</li>
<li>测试数据3</li>
</ul>
<input type="text" class="ipt-add-content" placeholder="添加内容"/>
<button id="btn-add-start">开头添加</button>
<button id="btn-add-end">结尾添加</button>
<script>
var ct=document.querySelector('.ct'),
addStartBtn=document.querySelector('#btn-add-start'),
addEndBtn=document.querySelector('#btn-add-end'),
ipt=document.querySelector('.ipt-add-content');
ct.addEventListener('click',function(e){
if(e.target.tagName.toLowerCase()==='li'){
console.log(e.target.innerText);
}
});
addEndBtn.addEventListener('click', function(){
if(!ipt.value){
alert('文本输入框必须输入内容');
return;
}else{
let newLi=document.createElement('li');
newLi.innerText=ipt.value;
ct.appendChild(newLi);
ipt.value='';
}
});
addStartBtn.addEventListener('click', function(){
if(!ipt.value){
alert('文本输入框必须输入内容');
return;
}else{
let newLi=document.createElement('li');
newLi.innerText=ipt.value;
ct.insertBefore(newLi, ct.firstChild);
ipt.value='';
}
});
</script>
</body>
</html>
题目7: 补全代码,要求:当鼠标放置在li元素上,会在img-preview里展示当前li元素的data-img对应的图片。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<ul class="ct">
<li data-img="http://cdn.jirengu.com/book.jirengu.com/img/11.jpg">鼠标放置查看图片</li>
<li data-img="http://cdn.jirengu.com/book.jirengu.com/img/13.jpg">鼠标放置查看图片</li>
<li data-img="http://cdn.jirengu.com/book.jirengu.com/img/14.jpg">鼠标放置查看图片</li>
</ul>
<div class="img-preview"></div>
<script text="text/javascript">
var ct = document.querySelector(".ct");
var list = document.querySelectorAll("li");
var preview = document.querySelector(".img-preview")
//利用循环来绑定事件
/*for(var i=0;i<list.length;i++){
list[i].addEventListener('click', function(){
//设置data-img变量来存储图片的网络地址
var data_img = this.getAttribute("data-img");
preview.innerHTML = "![]("+data_img+")";
}, false)
}
*/
//利用事件代理来实现事件绑定
ct.addEventListener('click', function(e){
var data_img = e.target.getAttribute('data-img');
preview.innerHTML = "![]("+data_img+")";
}, false)
</script>
</body>
</html>