事件对象event
DOM节点添加对象的两种方式
在介绍事件对象之前,我们先来了解给DOM节点添加对象的两种方式。
- 方式一:采用on+事件名的方式
<body>
<input type="button" value="点击" class="btn">
<script>
// 获取input节点
var btn = document.querySelector(".btn");
// 给按钮注册点击事件,点击按钮弹框弹出1
btn.onclick = function() {
alert(1)
};
// 再给按钮注册点击事件,点击按钮弹框弹出2
btn.onclick = function() {
alert(2)
};
// 此时,在浏览器中点击按钮的时候,页面中只会弹出2,而不是按顺序依次弹出1和2,那就说明给同一个节点注册相同的事件类型的时候,后面注册的事件会将前面注册的事件覆盖,只会执行最后注册的事件。
// 例如:给按钮注册相同的鼠标事件
btn.onmouseover = function() {
console.log(1);
}
btn.onmouseover = function() {
console.log(2);
}
// 在浏览器的控制台可以发现,只打印了2,那就说明后面注册的鼠标事件将前面的事件覆盖率。
</script>
</body>
- 方式二:采用 DOM节点.addEventListener(“事件名”, function() {})的方式。
- addEventListener() 用于向指定元素添加事件。可以向一个元素添加多次事件或者多次不同事件,后面的事件是不会覆盖前面的。
- 语法:
element.addEventListener(event,fn,useCaption );
参数说明:event 事件类型,比如 click mouseenter mouseleave
fn 回调函数
useCaption 用于描述是冒泡还是捕获。默认值是false,即冒泡传递。当值为true,就是捕获传递。
<body>
<input type="button" value="点击" class="btn">
<script>
// 获取input节点
var btn = document.querySelector(".btn");
// 给按钮注册点击事件,点击按钮弹框弹出1
btn.addEventListener("click", function() {
alert(1)
});
// 再给按钮注册点击事件,点击按钮弹框弹出1
btn.addEventListener("click", function() {
alert(2)
});
// 此时,在浏览器中点击按钮的时候,页面中会按顺序弹出1和2,那就说明给同一个节点注册相同的事件类型的时候,后面注册的事件不会将前面注册的事件覆盖,而是会依次执行。
</script>
</body>
事件执行的三个阶段
事件执行三个阶段:捕获、到达目标、冒泡
- 捕获:从根部节点一层一层往上找,直到找到我们刚才触发的那个节点,这个过程叫捕获;
- 到达目标:找到我们刚才触发的那个节点
- 冒泡:从找的目标节点,一层一层往往根节点找,这个过程叫冒泡;
// JS代码:注册事件 写不写这个代码,事件-三个阶段存在的;
var btn = document.querySelector("button");
btn.addEventListener("click", function() {
alert(1);
});
// 过程:点击btn后,信号从根部一层一层捕获到btn目标节点,发现btn 刚好注册了点击事件,函数被执行完,信号冒泡回到根节点;
特别注意(这是个规则):事件默认是在冒泡阶段执行;在冒泡的阶段,发现父级节点们也注册和用户触发的行为一样的事件,这些事件函数将会被执行;同样, 如果孙子没有点击事件, 但是用户对孙子有点击行为,但是爷爷注册有点击事件, 爷爷同样也会触发点击事件。
var box_3 = document.querySelector(".box_3");
box_3.addEventListener("click", function() {
alert(3);
});
// 父亲
var box_2 = document.querySelector(".box_2");
box_2.addEventListener("click", function() {
alert(2);
});
// 爷爷
var box_1 = document.querySelector(".box_1");
box_1.addEventListener("click", function() {
alert(1);
});
//在页面中执行的时候,点击box_3,页面中依次会弹出3,2,1。那就说明给box_2和box_1注册的事件也被执行了。也就是说明在冒泡的阶段,发现父级节点们也注册和用户触发的行为一样的事件,这些事件函数将会被执行;如果将box_3的事件注释掉,在页面中点击box_3,同样也会依次弹出2和1,那就说明,如果孙子没有点击事件, 但是用户对孙子有点击行为,但是爷爷注册有点击事件, 爷爷同样也会触发点击事件。
为什么事件默认是在冒泡阶段执行?用户体验好;让用户知道自己点的地方是正常;
var box_3 = document.querySelector(".box_3");
box_3.addEventListener("click", function() {
alert(3);
}, true);
// 父亲
var box_2 = document.querySelector(".box_2");
box_2.addEventListener("click", function() {
alert(2);
}, true);
// 爷爷
var box_1 = document.querySelector(".box_1");
box_1.addEventListener("click", function() {
alert(1);
}, true);
//如果在addEventListener传入第三个参数true,事件将在事件捕获阶段执行
阻止冒泡
在上面 的案例中我们发现,如果父级节点和子节点注册相同的事件,触发子节点的事件,不仅子节点的事件会执行,而且父级节点的事件也会被执行,这样会造成用户体验的不良好。怎么解决呢,那就是得阻止冒泡。阻止冒泡我们就得用到事件对象(后面详细介绍什么是事件对象)
// 体验:事件默认在冒泡阶段执行;
// 解决:阻止冒泡;
// 语法:需要在函数上设置形参e; e:事件对象;
// e.stopPropagation(); 阻止冒泡行为;
var box_3 = document.querySelector(".box_3");
box_3.addEventListener("click", function(e) {
alert(3);
// 阻止冒泡:冒泡行为没了,默认事件在冒泡阶段执行就不会出现了;
// e:形参!!!!!!!!!!!!!!!!!!!!!!事件对象;
// stop:停止,掐断;
// Propagation:传播,冒泡这条线;
e.stopPropagation();
});
// 父亲
var box_2 = document.querySelector(".box_2");
box_2.addEventListener("click", function(e) {
alert(2);
e.stopPropagation();
});
// 爷爷
var box_1 = document.querySelector(".box_1");
box_1.addEventListener("click", function() {
alert(1);
});
// 冒泡阻止后,在页面中点击谁就弹出谁的值
事件对象
上面说了那么多,现在我们就来详细说说什么是事件对象
事件对象:当我们触发document的click事件时,便会产生一个事件对象,这个对象中包含着这个事件的相关信息,包括导致事件的元素、事件的类型、以及其它与特定事件相关的信息等。这个对象是在执行事件时,浏览器通过函数传递过来的。通俗的说就是:事件对象有一些属性和方法,一些属性描述事件行为的位置的一个对象,这个对象就叫事件对象;
事件对象的使用:就是在注册事件的时候,给函数function传递一个参数e(e只是一个名词,叫什么无所谓,不过,一般情况下我们都叫e)。下面我们就打印一下事件对象中到底有什么
var box = document.querySelector(".box");
box.onclick = function(e){
console.log(e)
}
1、鼠标事件:上图就是打印出来的事件对象,它里面就是一些属性和方法,也可以把事件对象称为鼠标事件对象。我们可以通过事件对象来获取相关事件的一些属性,比如左键还是右键。在按键时,是否按住了所规定的键值如ctrl,shift等常用键,或者鼠标点击的位置等相关信息。
box.onclick = function(e) {
// 行为看成对象:对象,包含属性和方法,属性:描述鼠标点击的位置的属性;集合:事件对象;
// console.log(e);
// ------------------------------属性:
// console.log("x", "y");获取鼠标的位置
// console.log(e.clientX, e.clientY);// 参照当前可视窗口左上角为基准点
// console.log(e.pageX, e.pageY); //参照与body为左上角为基准点
// screenX/Y可获得在整个屏幕的横纵坐标。
//当然事件对象中还有很多属性,每一种属性都有不同的用处,针对不同的业务场景用不同的属性
}
2、键盘事件:主要应用于按键时,获取按下各个键值的键码或字符编码。主要发生在keydown和keypress事件中;keycode:不区分大小写,与键盘上的键值位置一一对应。用于keydown和keyup事;charcode:字符编码,区分大小写,其实返回的就是ASCII码。只支持keypress事件
<body>
<input type="text" id="text">
</body>
<script>
var ipt = document.querySelector("#text");
// 键盘按下的时候
ipt.onkeydown = function(e) {
console.log(e.keyCode, e.ctrlKey);//e.keyCode是当前按键的键码值,比如按下enter键,它的键码值就是13。e.ctrlKey只针对的是ctrl键,按下ctrl键才会打印true。
if (e.keyCode == 13) {
console.log("你按的是回车");
}
}
</script>
3、事件对象的方法:事件对象中的方法可以阻止默认一些默认行为,就比如说:阻止冒泡,页面中鼠标右击行为,还有a链接的跳转等等。
// 鼠标右键事件:页面中鼠标右击事件失效
document.oncontextmenu = function(e) {
// alert(1);
e.preventDefault();
}
// a标签:转跳;
var a = document.querySelector("a");
a.onclick = function(e) {
e.preventDefault();
}
4、事件对象中的this指向问题:
box.onclick = function(e) {
console.log(e.target); // 点击是谁就是谁;
// current:当前事件注册给谁就是谁;
// console.log(e.currentTarget);
// this: 事件注册给谁就是谁;
console.log(e.currentTarget == this); // true
}
总结:事件对象即是事件触发时,浏览器传递给事件处理的一个对象,通过这个对象,我们可以获得相应时间处理的一些相关信息,以便于我们对接下来的操作做进一步处理。