注册事件有两种方式:传统方式和方法监听注册方式
传统方式注册
注册事件具有唯一性:同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数。
addEventListener事件监听方式
eventTarget.addEventListener()
方法将指定的监听器注册到 eventTarget
(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。
特点:同一个元素同一个事件可以注册多个监听器,按注册顺序依次执行。
语法
eventTarget.addEventListener(type,listener[,useCapture])
参数
type
:事件类型字符串,比如click,mouseover,注意这里不要带on
listener
:事件处理函数,事件发生时,会调用该监听函数
useCapture
:可选参数,是一个布尔值,默认是 false。
attachEvent事件监听方式
与eventTarget.addEventListener()方法类似,不过参数不一样
语法
eventTarget.attachEvent(eventNameWithOn,callback)
参数
eventNameWithOn
:事件类型字符串,比如 onclick 、onmouseover ,这里要带 on
callback
: 事件处理函数,当目标触发事件时回调函数被调用
缺点:ie9以前的版本支持
<body>
<button>传统注册事件button>
<button>addEventListenerbutton>
<button>attachEventbutton>
<script>
var btns = document.querySelectorAll('button');
// 1. 传统方式注册事件
// 只执行后面的
btns[0].onclick = function() {
alert('1');
}
btns[0].onclick = function() {
alert('2');
}
// 2. 事件监听注册事件 addEventListener
// 两个都会依次执行
btns[1].addEventListener('click', function() {
alert(22);
})
btns[1].addEventListener('click', function() {
alert(33);
})
// 3. attachEvent ie9以前的版本支持
btns[2].attachEvent('onclick', function() {
alert(11);
})
script>
body>
传统方式删除事件
eventTarget.onclick = null;
removeEventListener删除事件方式
eventTarget.removeEventListener(type,listener[,useCapture]);
参数与addEventListener
事件监听方式的参数相同
detachEvent删除事件方式
eventTarget.detachEvent(eventNameWithOn,callback);
参数与attachEvent
事件监听方式的参数相同
<body>
<div>1div>
<div>2div>
<div>3div>
<script>
var divs = document.querySelectorAll('div');
divs[0].onclick = function() {
alert(11);
// 1. 传统方式删除事件
divs[0].onclick = null;
}
// 2.removeEventListener 删除事件
//里面的fn不需要调用加小括号,返回的是函数,加括号是调用
divs[1].addEventListener('click',fn);
function fn(){
alert(22);
divs[1].removeEventListener('click',fn);
}
// 3.IE9 中的删除事件方式
divs[2].attachEvent('onclick',fn1);
function fn1() {
alert(33);
divs[2].detachEvent('onclick',fn1);
}
script>
body>
事件流描述的是从页面中接收事件的顺序。事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即DOM事件流。
DOM事件流分为3个阶段:
理解
注意:JS 代码中只能执行捕获或者冒泡其中的一个阶段,不能同时执行。
事件捕获阶段
在事件捕获过程中,document对象首先接收到click事件,然后事件沿着DOM树依次向下,一直传播到事件的实际目标。
即document -> html -> body -> div
<body>
<div class="father">
<div class="son">son盒子div>
div>
<script>
// 如果addEventListener 第三个参数是 true 那么则处于捕获阶段
var son = document.querySelector('.son');
son.addEventListener('click', function() {
alert('son');
}, true);
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, true);
script>
body>
此时点击子盒子,会先弹出 father,之后再弹出 son。
事件冒泡阶段
事件开始时有最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
即div -> body -> html -> document
<body>
<div class="father">
<div class="son">son盒子div>
div>
<script>
// 如果addEventListener 第三个参数是 false或省略 那么则处于冒泡阶段
var son = document.querySelector('.son');
son.addEventListener('click', function() {
alert('son');
}, false);
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, false);
document.addEventListener('click', function() {
alert('document');
})
script>
body>
此时点击子盒子,会先弹出 son,之后再弹出 father。
事件对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。
如:
eventTarget.onclick = function(event) {
}
event就是此事件的事件对象
事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,事件对象有很多属性和方法:
注意:event 是个形参,系统帮我们设定为事件对象,不需要传递实参过去;当我们注册事件时, event 对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)
事件对象的兼容性问题
事件对象本身的获取存在兼容问题:
解决:
<body>
<div>123div>
<script>
// 事件对象
var div = document.querySelector('div');
div.onclick = function(e) {
// 解决兼容性问题
// console.log(e);
// console.log(window.event);
// e = e || window.event;
console.log(e);
}
script>
body>
事件对象的常见属性和方法
事件对象属性方法 | 说明 |
---|---|
e.target | 返回触发事件的对象 标准 |
e.srcElement | 返回触发事件的对象 非标准 ie6-8使用 |
e.type | 返回事件的类型 比如click mouseover 不带on |
e.cancelBubble | 该属性阻止冒泡,非标准,ie6-8使用 |
e.returnValue | 该属性阻止默认行为 非标准,ie6-8使用 |
e.preventDefault() | 该方法阻止默认行为 标准 比如不让链接跳转 |
e.stopPropagation() | 阻止冒泡 标准 |
e.target 和 this 的区别:
this
是事件绑定的元素, 这个函数的调用者(绑定这个事件的元素)e.target
是事件触发的元素。事件对象阻止默认行为
html中一些标签有默认行为,例如a标签被单击后,默认会进行页面跳转。可以通过事件对象阻止这种默认行为。
方法
e.preventDefault()
方法 DOM标准returnValue
属性 低版本浏览器 ie678适用return false
传统的注册方式,return 后面的代码不能执行<body>
<div>123div>
<a href="http://www.baidu.com">百度a>
<form action="http://www.baidu.com">
<input type="submit" value="提交" name="sub">
form>
<script>
// 1. 返回事件类型
var div = document.querySelector('div');
div.addEventListener('click', fn);
div.addEventListener('mouseover', fn);
div.addEventListener('mouseout', fn);
function fn(e) {
console.log(e.type);
}
// 2. 阻止默认行为(事件) 让链接不跳转 或者让提交按钮不提交
var a = document.querySelector('a');
a.addEventListener('click', function(e) {
e.preventDefault(); // dom 标准写法
})
// 3. 传统的注册方式
a.onclick = function(e) {
return false;
alert(11);
}
script>
body>
阻止事件冒泡
方法
e.stopPropagation()
方法 e.cancelBubble = true;
<body>
<div class="father">
<div class="son">son儿子div>
div>
<script>
// 阻止冒泡 dom 推荐的标准 stopPropagation()
var son = document.querySelector('.son');
son.addEventListener('click', function(e) {
alert('son');
e.stopPropagation(); // stop 停止 Propagation 传播
e.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
}, false);
// 点击father仍会冒泡,所以father也要添加
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, false);
document.addEventListener('click', function() {
alert('document');
})
script>
body>
事件委托也称为事件代理,在 jQuery 里面称为事件委派
为什么要用事件委托
DOM需要有事件处理程序,我们都会直接给它设事件处理,但是如果有非常多的DOM需要添加事件,比如100个li,每个li都有相同的click点击事件,可能我们会用for循环的方法,来遍历所有的li,然后给它们添加事件,但是这样做会有很大的缺点:
事件委托原理——事件冒泡
事件委托利用事件冒泡(从最深的节点开始,然后逐步向上传播事件)只在他们的父元素上指定一个事件处理程序,就可以管理某一类型的的所有事件。
<body>
<ul>
<li>1li>
<li>2li>
<li>3li>
<li>4li>
ul>
<script>
// 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
// e.target 这个可以得到我们点击的对象
e.target.style.backgroundColor = 'pink';
// 如果点了全部则ul全是pink色
// 点了谁,就让谁的style里面的backgroundColor颜色变为pink
})
script>
body>
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
禁止鼠标右键与鼠标选中
contextmenu
主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
selectstart
禁止鼠标选中
<body>
<p>文字p>
<script>
// 1. 禁用右键菜单
// 点击右键不能显示菜单
document.addEventListener('contextmenu', function(e) {
e.preventDefault(); // 阻止默认行为
})
// 2. 禁止选中文字
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})
script>
body>
鼠标事件对象
鼠标事件对象 | 说明 |
---|---|
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
e.pageX(一般使用) | 返回鼠标相对于文档页面的X坐标 IE9+ 支持 |
e.pageY(一般使用) | 返回鼠标相对于文档页面的Y坐标 IE9+ 支持 |
e.screenX | 返回鼠标相对于电脑屏幕的X坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的Y坐标 |
键盘事件 | 触发条件 |
---|---|
onkeyup | 某个键盘按键被松开时触发 |
onkeydown | 某个键盘按键被按下时触发 |
onkeypress | 某个键盘按键被按下时触发,但是它不识别功能键,比如 ctrl shift 箭头等 |
三个事件的执行顺序是: keydown – keypress — keyup
键盘事件对象
键盘事件对象 | 说明 |
---|---|
e.keyCode | 返回该键值的ASCII值 |