事件高级
学习内容
- 注册事件
- 删除事件
- DOM事件流
- 事件对象
- 阻止事件冒泡
- 事件委托(代理,委派)
- 常用的鼠标事件
- 常用的键盘事件
1.1注册事件的概述
listener
监听 addEventListener
事件监听方式
给元素添加事件,称为注册事件或者绑定事件。
注册时间有两种办法:传统方式和方法监听注册方式
传统的注册方式
- 利用on开头的事件
btn.onclick=function(){}
- 特点:注册事件的唯一性
- 同一元素的同一事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
方法监听注册方式
eventTarget.addEventListener(type,listener[,useCapture])
//该方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数,IE9之前的不支持此方法可以使用attachEvent()
//同一元素同一事件可以注册多个监听器
//按注册顺序执行
//type事件类型字符串,比如click,mouseover,注意不要加on
//listener事件处理函数,事件发生时,会调用监听函数
//useCapture:可选参数
btn.addEventListener('click',function(){alert(hello world);})
.attachEvent('onclick',function(){});
IE9-才可以使用,注意兼容
//注册事件兼容性解决方案(了解)
function addEventListener(element, eventName, fn) {
//判断当前浏览器是否支持addEventListener;
if (element.addEventListener) {
element.addEventListener(eventName, fn);
} else if (element.attachEvent) {
element.attachEvent('on' + eventName, fn);
} else {
//btn.οnclick=fn;
element['on' + element] = fn;
}
}
兼容处理原则:先照顾大多数的浏览器,在处理少数的。
删除事件
btn.onclick=null;
btn.removeEventListener('click' ,fn)
function fn(){
alert("hi");
}
btn.datachEvent("onclick",fn);//(IE7-)
//兼容写法解决方案(了解)
function removeEvenListener(element,eventName,fn){
//判断当前浏览其是否支持removeEventListener方法
if(element.removeEvenListener){
element.removeEvenListener(eventName,fn);//第三个参数默认false
}
else if (element.detachEvent){
element.datachEvent('on'+eventName,fn);
}
else{
element['on'+eventName]=null;
}
}
DOM的事件流
事件流描述的从页面中接收事件的顺序
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件
- 事件捕获阶段
- 目标阶段
- 冒泡阶段
可以改变事件的执行顺序
事件捕获从document——》html——》body——》div
事件冒泡从div ——》body——》html——》document
在执行时如果有事件就会执行,没有的话继续执行下一个。
- JS代码中只能执行捕获或者冒泡其中的一个阶段
onclick
和attachEvent
只能执行冒泡阶段addEventListener[useCapture]
第三个参数如果是true
,表示在事件捕获阶段调用事件处理程序,如果是false
(不写默认是false)则是冒泡阶段- 有些事件没有冒泡的比如
onblur
onfocus
onmouseenter
onmouseleave
事件流的代码理解
<style>
.father {
width: 300px;
height: 300px;
background-color: pink;
}
.son {
width: 200px;
height: 200px;
background-color: yellow;
}
.sister {
width: 100px;
height: 100px;
background-color: green;
}
</style>
<body>
<div class="father">
<div class="son">
<div class="sister">
<button>按钮</button>
</div>
</div>
</div>
<script>
var divs = document.querySelectorAll('div');
var btn = document.querySelector('button');
// 这样是事件冒泡,从点击的事件一层层向外流动。若是绑定事件便会执行
divs[0].addEventListener('click', function () { alert('father'); });
divs[1].addEventListener('click', function () { alert('son'); });
divs[2].addEventListener('click', function () { alert('sister'); });
btn.addEventListener('click', function () { alert('btn') });
</script>
</body>
//这是事件捕获,从外向内一层层执行
// useCature属性值来决定,true为捕获,false或不写为冒泡(常用)
divs[0].addEventListener('click', function () { alert('father'); }, true);
divs[1].addEventListener('click', function () { alert('son'); }, true);
divs[2].addEventListener('click', function () { alert('sister'); }, true);
btn.addEventListener('click', function () { alert('btn') }, true)
事件对象
eventTarget.onclick=function(event){}
eventTarget.addEventListener('click' , function(event){})
这个event
是个形参,系统会帮我们设定为事件对象,不需要我们传递实参进去
当我们注册事件时,event
对象就会被系统自动创建,依次传递给事件监听器
event
就是一个事件对象,写到我们的侦听函数的小括号里
一些事件是由用户触发的,例如鼠标或键盘事件
事件对象是我们事件的一系列相关数据的集合,跟事件相关的比如鼠标点击里面就包含了鼠标相关的信息,键盘事件里就包含了键盘事件的信息比如用户按了那个键。
这个事件对象我们可以自己命名 比如 event、evt 、e
兼容问题在IE678里面通过window.event
获取
//兼容写法
div.onclick=function(e){
e=e||window.event;
console.log(window.event);//在ie678里使用
}
事件属性方法
target
返回的是触发事件的对象
this
是绑定事件的对象
e.type
返回事件的类型比如click`` mouseover
e.cancelBubble =true;
该属性阻止冒泡 非标准IE6-8 cancel取消 bubble 泡泡
e.stopPropagation()
阻止冒泡 标准stop 停止 propagation 传播
e.returnValue
该方法阻止默认行为 非标准 Ie6-8
e.preventDefault()
该方法阻止默认事件 标准 比如不让页面跳转
//target返回的是触发事件的对象
//this是绑定事件的对象
var ul=doucument.querySelector('ul');
ul.addEventListener('click',function(e){
console.log(this);//返回的是绑定的事件ul
console.log(e.currentTarget)//和this相似,绑定事件
console.log(e.target);//返回的是点击事件li
})
兼容写法
div.onclick=function(e){
e=e||window.event;
console.log(e.srcElement);//兼容写法,返回点击事件
}
//返回事件类型
var div = document.querySelector('div');
div.addEventListener('click',fn);
div.addEventListener('mouseover',fn);
div.addEventListener('mouseout',fn);
function fn(e){
console.(e.type);//返回事件类型,click ,mouseover 不带on;
}
//阻止默认行为(事件)
var a = document.querySelector('a');
a.addEventListener('click',function(e){
a.preventDefault();//dom标准写法
})
//传统写法
a.onclick=function(e){
//现代浏览器使用
e.prevenDefault();
//低版本IE678
e.returnValue;
//兼容的话以上两个同时写,可以解决
//我们可以使用return false也能阻止兼容性的问题,只是return后的代码不执行
return false;
}
//阻止冒泡
//事件冒泡:开始由最具体的元素接收,然后逐级向上传播到DOM最顶层节点
e.stopPropagation();//标准
e.cancelBubble = true;//ie678
事件委托
原理:不是给每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上然后通过冒泡影响每一个子节点
//案例理解
<ul>
<li>hello world</li>
<li>hello world</li>
<li>hello world</li>
<li>hello world</li>
<li>hello world</li>
</ul>
<script>
var ul = document.querySelector('ul');
var list=dovument.querySelectorAll('li');
ul.addEventListener('click', function (e) {
//点击li,但是通过事件冒泡,触发ul的事件
//没有给li设置click为什么可以点击:
// 这是因为这里使用的是事件监听,可以得到对li点击这一事件
alert('你好,请点赞');
//排他思想
for (var i = 0; i < list.length; i++) {
list[i].style.backgroundColor = '';
}
// 改变点击的背景色,通过e.target获得点击的事件。让后进行修改
e.target.style.backgroundColor = 'pink';
})
</script>
常用的鼠标事件
1 禁止鼠标右键菜单
contextmenu
主要控制应该在何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
document.addEventListener('contextmenu',founction(e){
e.preventDefault();//阻止默认行为
})
2禁止鼠标选中
selectstart
document.addEventListener('selectstart',functon(e){
e.preventDefault();
})
鼠标事件对象
event
代表事件的状态,跟事件相关的一系列信息的集合,现阶段我们主要是用鼠标事件对象MouseEvent
和键盘对象KeyboardEvent;
鼠标事件对象 | 说明 |
---|---|
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
e.pageX | 返回鼠标相对于文档页面的X坐标IE-9+ |
e.pageY | 返回鼠标相对于文档页面的Y坐标IE-9+ |
e.screenX | 返回鼠标相对于电脑屏幕的X坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的Y坐标 |
鼠标移动事件mousemove
只要鼠标移动1px就会触发事件
做一个跟随鼠标的小天使案例
案例分析
- 鼠标不断移动,使用鼠标移动事件
mousemove
- 在页面中移动,给document注册事件
- 图片要移动,给document注册事件
- 核心原理:每次移动树表示都会获取最新的鼠标坐标。吧这个x和Y坐标作为图片的top和left的值就可以移动图片了
<!-----案例--->
<!----注意给图片添加定位(固定定位就可以)---->
/* <style>
img {
position: fixed;
top: 0px;
left: 0px;
}
</style>*/
<body>
<img src="./images/angel.gif" alt="">
<script>
var img = document.querySelector('img');
// 注意这里是给document注册事件的,如果给图片注册事件,就变成了鼠标要放到图片上才会跟着走的。
// 并且,也没用鼠标一进页面图片就跟随的效果
document.addEventListener('mousemove', function (e) {
//获取鼠标在页面文档的坐标
var x = e.pageX;
var y = e.pageY;
// 这里可以给鼠标做下计算,让鼠标位于图片的中央
img.style.top = (y - 40) + 'px';
img.style.left = (x - 48) + 'px';
})
</script>
附:
键盘事件
键盘事件 | 触发条件 |
---|---|
onkeyup | 某个键盘按键被松开 时触发 |
onkeydown | 某个键盘按键被按下 时触发 |
onkeypress | 某个键盘按键被按下 时触发 但是他不能识别功能键,比如Ctrl shift等 |
- 如果使用
addEventListener
不需要加on onkeypress
不识别功能键- 如果同时添加三个事件时,执行顺序
onkeydown
——》onkeypress
——》onkeyup
键盘事件对象keybodevent
key
可以得到按得值,有兼容性
keyCode
可以获取按下键的ASCII码值
keyup
和 keydown
事件不区分字母大小写。字母大小写返回的是相同的ASCII值(推荐)
keypress
区分字母大小写 但他不识别功能键a 97 ; A 65;
document.addEventListener('keypress',function(e){
console.log(e.keyCode);//可以得到按下键的ASCII
if (e.keyCode==65){
alert('按下的是A');
}else{
alert('没有按下A')
}
})
fouce()方法获取焦点
快递单号案例
* {
margin: 0;
padding: 0;
}
.search {
position: relative;
width: 178px;
margin: 100px;
}
.con {
display: none;
position: absolute;
top: -40px;
width: 171px;
border: 1px solid rgba(0, 0, 0, .2);
box-shadow: 0 2px 4px rgba(0, 0, 0, .2);
padding: 5px 0;
font-size: 18px;
line-height: 20px;
color: #333;
}
.con::before {
content: '';
width: 0;
height: 0;
position: absolute;
top: 28px;
left: 18px;
border: 8px solid #000;
border-style: solid dashed dashed;
border-color: #fff transparent transparent;
}
<body>
<div class="search">
<div class="con">123</div>
<input type="text" placeholder="请输入您的快递单号" class="jd">
</div>
<script>
// 快递单号输入内容时, 上面的大号字体盒子(con)显示(这里面的字号更大)
// 表单检测用户输入: 给表单添加键盘事件
// 同时把快递单号里面的值(value)获取过来赋值给 con盒子(innerText)做为内容
// 如果快递单号里面内容为空,则隐藏大号字体盒子(con)盒子
var con = document.querySelector('.con');
var jd_input = document.querySelector('.jd');
jd_input.addEventListener('keyup', function() {
// console.log('输入内容啦');
if (this.value == '') {
con.style.display = 'none';
} else {
con.style.display = 'block';
con.innerText = this.value;
}
})
// 当我们失去焦点,就隐藏这个con盒子
jd_input.addEventListener('blur', function() {
con.style.display = 'none';
})
// 当我们获得焦点,就显示这个con盒子
jd_input.addEventListener('focus', function() {
if (this.value !== '') {
con.style.display = 'block';
}
})
</script>
</body>
keydown
keypress
在文本框中特点,先触发事件,文字还没有落入文本框中
keyup
在事件触发后,文字落入文本框中