目录
1. 注册事件(绑定事件)
给元素添加事件,成为注册事件或者绑定事件
注册事件有两种方式:传统方式和方法监听注册方式
1)传统注册方式
- 利用on开头的时间onclick
- <button onclick = "alert('hi')" ></button>
- btn.onclick = function() {}
- 特点:注册事件的唯一性
- 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
2)方法监听注册
- W3C标准,推荐方式
- addEventListener()是一个方法
- IE9之前的IE不支持此方法,可使用attachEvent()代替
- 特点:同一个元素同一个事件可以注册多个监听器
- 按注册顺序依次执行
addEventListener 事件监听方式
<body>
<button>传统方式注册事件</button>
<button>方法监听注册事件</button>
<script>
var btns = document.querySelectorAll('button');
//1.传统方式
btns[0].onclick = function() {
alert("111");
}
//注册事件的唯一性
//同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
//最后按下按钮显示的是 222
btns[0].onclick = function() {
alert("222");
}
//2.方法监听方式,事件类型是字符串需要加引号,并且不带on
//同一个元素同一个事件可以注册多个监听器
//按注册顺序执行
//按下按钮显示的结果依次为 333 666
btns[1].addEventListener('click', function() {
alert('333');
});
btns[1].addEventListener('click', function() {
alert('666');
});
</script>
</body>
结果为:
attachEvent 事件监听方式
2. 删除事件(解绑事件)
1)传统删除方式
eventTarget.onclick = null;
2)方法监听删除事件
eventTarget.removeEventListener(type, listener[, useCapture]);
eventTarget.detachEvent(eventNameWithOn, callback);
<style>
div {
width: 200px;
height: 200px;
background-color: #ccc;
}
</style>
</head>
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<script>
var divs = document.querySelectorAll('div');
//1.传统方式解绑事件
divs[0].onclick = function() {
alert(111);
divs[0].onclick = null;
}
//2.方法监听删除事件
// divs[1].addEventListener('click', fn);
function fn() {
alert(222);
divs[1].removeEventListener('click',fn);
}
divs[2].attachEvent('onclick', fn1);
function fn1() {
alert(333);
divs[2].detachEvent('onclick', fn1);
}
</script>
</body>
结果为:
3. DOM事件流
事件流描述的是从页面中接受事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。
DOM事件流分为3个阶段:
- 捕获阶段:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到最具体的元素接受的过程
- 当前目标阶段
- 冒泡阶段:IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程
注意⚠️:
- JS代码中只能执行捕获或者冒泡中的一个阶段
- onclick和attachEvent只能得到冒泡阶段
- addEventListener(type, listener[, useCapture])第三个参数如果是true,表示在事件捕获阶段调用事件处理程序,如果是false(默认是false),表示在事件冒泡阶段调用事件处理程序
<style>
.father {
width: 500px;
height: 500px;
border: 1px solid #000;
margin: auto;
}
.son {
width: 300px;
height: 300px;
background-color: antiquewhite;
margin: 100px;
}
</style>
</head>
<body>
<div class="father">
<div class="son">son</div>
</div>
<script>
var father = document.querySelector('.father');
var son = document.querySelector('.son');
//1.第三个参数如果是true,表示在事件捕获阶段调用事件处理程序
//document -> html -> body -> father -> son
father.addEventListener('click', function() {
alert('father');
},true);
//先弹出father,再弹出son
son.addEventListener('click', function() {
alert('son');
},true);
//2.第三个参数是false(默认是false),表示在事件冒泡阶段调用事件处理程序
// son -> father -> body -> html -> document
// son.addEventListener('click', function() {
// alert('son');
// },false);
//先弹出son,再弹出father,然后再弹出document
// father.addEventListener('click', function() {
// alert('father');
// },false);
// document.addEventListener('click', function() {
// alert('document');
// })
</script>
</body>
结果为:
4. 事件对象
- event对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态
- 事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,它有很多属性和方法
- event是形参,系统帮我们设定为事件对象,不需要传递实参过去
- 当注册事件时,event对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)
- 在标准浏览器中是浏览器给方法传递的参数,只需要定义形参e就可以获取到
- 在IE6-8中,浏览器不会给方法传递参数,如果需要的话,需要到window.event中获取查找
<style>
div {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div>123</div>
<script>
var div = document.querySelector('div');
//1.event就是一个事件对象,在真挺函数的小括号里当作形参
//2.事件对象只有有了时间才会存在,是系统帮我们自动创建的,不需要传递实参
//3.事件对象是时间的一系列相关数据的集合,比如:鼠标单击就包含了鼠标的相关信息
//4.这个事件对象也可以自命名,比如event、evt、e
div.addEventListener('click', function(event) {
//兼容性写法:event = event || window.event
event = event || window.event;
console.log(event);
});
</script>
</body>
结果为:
事件对象的常见属性和方法
<style>
div {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div>123</div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
//1.e.target:返回的是触发事件的对象(元素),this返回的是绑定事件的对象(元素)
//e.target谁点击了哪个事件就返回谁,this哪个元素绑定了这个事件就返回哪个元素
var div = document.querySelector('div');
div.addEventListener('click', function(e) {
console.log(e.target);
console.log(this);
});
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
//返回的是触发事件的对象,即点击li才触发了这个事件,返回的是li
console.log(e.target);
//返回的是绑定事件的对象,即给ul绑定了事件,返回的是ul
console.log(this);
})
</script>
</body>
结果为:
<body>
<div>123</div>
<a href="https://www.baidu.com">百度</a>
<script>
var div = document.querySelector('div');
div.addEventListener('click', fn);
div.addEventListener('mouseover', fn);
div.addEventListener('mouseout',fn);
function fn(e) {
//1.返回事件的类型,不带on
console.log(e.type);
}
//2.阻止默认事件让链接不跳转,或者让提交按钮不提交
var a = document.querySelector('a');
a.addEventListener('click', function(e) {
//DOM标注写法ß
e.preventDefault();
});
a.onclick = function(e) {
//普通浏览器
e.preventDefault;
//低版本浏览器
e.returnValue;
//没有兼容性问题,但是return之后的语句无法执行
return false;
}
</script>
</body>
结果为:
5. 防止事件冒泡
事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点
标准写法:利用事件对象里面的stopPropagation()方法
兼容性解决方案:
<style>
.father {
width: 500px;
height: 500px;
border: 1px solid #000;
margin: auto;
}
.son {
width: 300px;
height: 300px;
background-color: antiquewhite;
margin: 100px;
}
</style>
</head>
<body>
<div class="father">
<div class="son">son</div>
</div>
<script>
var father = document.querySelector('.father');
var son = document.querySelector('.son');
//2.第三个参数是false(默认是false),表示在事件冒泡阶段调用事件处理程序
// son -> father -> body -> html -> document
son.addEventListener('click', function(e) {
alert('son');
//阻止事件冒泡,即只显示son,不显示father document
e.stopPropagation();
e.cancelBubble = true;
},false);
//先弹出son,再弹出father,然后再弹出document
father.addEventListener('click', function() {
alert('father');
},false);
document.addEventListener('click', function() {
alert('document');
})
</script>
</body>
结果为:
6. 事件委托(代理、委派)
事件委托也称为事件代理,在jQuery里面称为事件委派
1)原理
不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
2)作用
只操作了一次DOM,提高了程序的性能
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
//事件委托原理:给父节点添加事件监听器,利用事件冒泡影响每一个子节点
var ul = document.querySelector('ul');
//给ul注册点击事件,利用事件对象的target来找到当前点击的li,点击了li事件就会冒泡到ul上,ul有监听器所以会触发事件监听器
ul.addEventListener('click', function() {
alert('点击了li');
})
</script>
</body>
结果为:
7. 常用的鼠标事件
- 禁止鼠标右键菜单:contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
- 禁止鼠标选中(selectstart开始选中)
鼠标事件对象
event对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段主要使用鼠标事件对象MouseEvent 和 键盘事件对象 KeyboardEvent。
<style>
body {
height: 3000px;
}
</style>
</head>
<body>
<script>
//鼠标事件对象MouseEvent
document.addEventListener('click', function(e) {
//1.client 鼠标在可视区的x和y坐标
console.log('鼠标在可视区内的坐标');
console.log(e.clientX);
console.log(e.clientY);
//2.page 鼠标在页面文档的x和y坐标
console.log('鼠标在页面文档的坐标');
console.log(e.pageX);
console.log(e.pageY);
//3.screen 鼠标在电脑屏幕的x和y坐标
console.log('鼠标在电脑屏幕的坐标');
console.log(e.screenX);
console.log(e.screenY);
});
</script>
</body>
结果为:
移动鼠标的天使案例
<style>
img {
position: absolute;
}
</style>
</head>
<body>
<img src="images/angel.gif" alt="">
<script>
var img = document.querySelector('img');
document.addEventListener('mousemove', function(e) {
//核心原理:每次鼠标移动都会获得x和y坐标,根据这个坐标来设置图片的left和top值,然后拖动图片
var x = e.pageX;
var y = e.pageY;
img.style.left = x - 40 + 'px';
img.style.top = y - 40 + 'px';
});
</script>
结果为:
8. 常用的键盘事件
- 如果使用addEventListener不需要加on
- onkeypress和前面2个的区别:它不识别功能键,比如左右箭头、shift、ctrl等
- 三个事件的执行顺序是:keydown - keypress - keyup
<body>
<script>
//三个事件的执行顺序是:keydown - keypress - keyup
//1.keyup 键盘松开时触发
document.addEventListener('keyup', function() {
console.log('松开了');
});
//2.keydown 键盘按下时触发
document.addEventListener('keydown', function() {
console.log('按下了 down');
});
//3.keypress 键盘按下时触发,但是不识别左右箭头、shift等功能按键
document.addEventListener('keypress', function() {
console.log('按下了 press');
});
</script>
</body>
结果为:
键盘事件对象
- onkeydown和onkeyup不区分字母大小写,onkeypress区分字母大小写
- keyup、keydown能识别所有的键,包括功能键
- keypress不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCII值
<body>
<script>
//键盘事件中的keyCode属性可以得到相应键的ASCII值
//1.keyup和keydown事件不区分字母大小写,A和a得到的ASCII值都是65
//2.keypress事件区分大小写,A得到的ACSCII值是65,a得到的ASCII值是97
document.addEventListener('keyup', function(e) {
console.log('keyup:' + e.keyCode);
});
document.addEventListener('keypress', function(e) {
console.log('keypress:' + e.keyCode);
});
document.addEventListener('keydown', function(e) {
console.log('keydown:' + e.keyCode);
});
</script>
</body>
结果为:
模拟京东按键输入内容案例
<body>
<input type="text" name="" id="">
<script>
//检测用户是否按下s键,如果是,则将光标定位到搜索框内
//1.使用键盘事件对象的keyCode属性判断用户是否按下s键
//2.搜索框获得焦点:js的focus()方法
var search = document.querySelector('input');
//由于keyup不识别大小写,所以s的keyCode为83
document.addEventListener('keyup', function(e) {
if(e.keyCode == 83) {
search.focus();
}
})
</script>
</body>
结果为:只要用户按下s键,则将光标自动移动到搜索框内