一、事件的组成与执行过程
1、事件的组成
事件是JS检测到的一种行为,触发响应的机制。事件的组成三部分组成:
事件源:事件被触发的对象,如按钮,标签;
事件类型:如何触发,什么事件,鼠标点击触发,经过触发,滚动触发……,onclick()
事件处理程序:通过函数赋值的方式执行;
<body>
<button id="btn">点击看看</button>
<script>
var btn = document.getElementById('btn')//1.事件源
btn.onclick = function() {//2.事件类型
alert('点击会弹出一个框');//3.处理事件的程序
}
</script>
</body>
2、执行过程
点击一次就打印一次,再如关闭广告的功能,我的理解是给某个元素一个事件,在这个事件中点击的时候,让元素隐藏,就实现了关闭广告的功能。
<script>
var div = document.querySelector('div');
div.onclick = function() {
console.log('点击看看效果');
}
</script>
二、事件的注册与删除
1、注册事件
(1)传统的注册事件可以出现在<script></script>、元素、JS文件中,其特点是唯一性。同一个元素同一个事件只能设置一个处理函数,并且后面的函数会覆盖前面注册的函数。
<body>
<button>按钮1</button>
<button>按钮2</button>
<script>
//all,是选择所有元素,返回结果是个数组,因此,他与btn[i]对应
var btn = document.querySelectorAll('button')
btn[0].onclick = function() {
alert('abcde');
}
btn[0].onclick =function() {
alert('hao a u');
}
</script>
</body>
(2)addEventListener()方法,可以实现同一个元素同一个事件可以注册多个监听器,并且按照注册的先后顺序执行。
<body>
<button>按钮1</button>
<button>按钮2</button>
<script>
//all,是选择所有元素,返回结果是个数组,因此,他与btn[i]对应
var btn = document.querySelectorAll('button')
//addEventListen('',function(){})方法,存在兼容性问题,要求IE9以上;第一个参数是事件类型,以字符串的方式存在,不要带on,第二个参数是侦听器(事件处理函数);同一个元素同一个事件,可以注册多个侦听器,并且按照注册的先后顺序执行。
btn[1].addEventListener('click',function() {
alert('22');
});
btn[1].addEventListener('click',function() {
alert('33');
});
btn[1].addEventListener('click',function() {
alert('44');
});
</script>
</body>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<script>
var btn = document.querySelectorAll('button')
//IE9以下浏览器才支持,第一个参数是事件类型,以字符串的形式存在,必须要加on;第二个参数是侦听器
btn[2].attachEvent('onclick',function() {
alert('abc')
})
</script>
</body>
兼容性解决方案,先判断是否支持addEventListener(),再判断是否支持attachEvent(),如果上述两种方式都不支持,则使用传统注册方式:onlclick。
2、删除事件
根据添加事件的3种方法,衍生出删除事件的3种方法。删除事件配合添加事件,可以实现让事件在一个元素上实现一次。
<body>
<div>删除事件1</div>
<div>删除事件2</div>
<div>删除事件3</div>
<script>
var divs = document.querySelectorAll('div');
divs[0].onclick = function() {
alert(11);
//1.删除传统事件的方法,直接让其值=null即可
divs[0].onclick = null;
}
divs[1].addEventListener('click',fn);
function fn() {
alert(22);
//2.删除addEventListen()方法的事件,不用在匿名函数中删除;要在添加事件之前就考虑到后期的删除事件可能,单独定义函数;同时要注意,调用函数时用函数名即可,不用加小括号。
divs[1].removeEventListener('click',fn);
}
divs[2].attachEvent('onclick',fn1);
function fn1() {
alert(33);
//3.老版本浏览器才兼容
divs[2].detachEvent('onclick',fn1);
}
</script>
</body>
3、DOM事件流
DOM事件流,是事件的传播过程,分为自上而下的捕获阶段、自下而上的冒泡阶段以及当前的目标阶段。冒泡比较常用。
<body>
<style>
.father {
width: 100px;
height: 100px;
background-color: red;
}
.son{
width: 50px;
height: 50px;
background-color: blue;
}
</style>
<div class="father">
<div class="son"></div>
</div>
<script>
//1.addEventListen()第三个参数如果为true,则按捕获阶段执行,即从document->html->body->father->son
var div1 = document.querySelector('.son');
div1.addEventListener('click',function(){
alert('son');
},true)
var div2 =document.querySelector('.father');
div2.addEventListener('click',function(){
alert('father');
},true)
//2.addEventListen()第三个参数如果为false或者省略,则按冒泡阶段执行,即从son->father->body->html->document;这两个阶段,其实就是从外到内,从内到外的执行过程。
var div1 = document.querySelector('.son');
div1.addEventListener('click',function(){
alert('son');
},false)
var div2 =document.querySelector('.father');
div2.addEventListener('click',function(){
alert('father');
},false)
</script>
</body>
4、事件对象
(1)什么是事件对象?
<body>
<style>
.father {
width: 100px;
height: 100px;
background-color: red;
}
.son{
width: 50px;
height: 50px;
background-color: blue;
}
</style>
<div class="father">
<div class="son"></div>
</div>
<script>
var son = document.querySelector('.son');
//1.event就是一个事件对象,写侦听器的小括号里,当形参来看,名子任意写,如e,evt等;
//2.事件对象只要有了事件只要有了事件就会出现,不需要额外再传递实参;
//3.事件对象是一系列相关数据的集合,例如,如果是鼠标事件,就是鼠标鼠标相关数据的集合,例如鼠标的坐标;如果是键盘事件,那就是键盘数据的相关集合,例如按了哪个键;
//4.事件对象也有兼容性问题,IE6/7/8,使用window.event
son.onclick = function(event) {
console.log(event);
}
var father = document.querySelector('.father');
father.addEventListener('click',function(e){
console.log(e);
})
</script>
</body>
(2)事件对象与this的区别
<body>
<style>
.father {
width: 100px;
height: 100px;
background-color: red;
}
.son{
width: 50px;
height: 50px;
background-color: blue;
}
</style>
<div class="father">
<div class="son"></div>
</div>
<script>
var father = document.querySelector('.father');
father.onclick = function(event) {
//this,绑定了哪个元素,他就指代哪个元素
console.log(this);
//事件对象event.target,谁触发了事件,它就指代哪个事件对象
console.log(event.target);
}
</script>
</body>
5、阻止事件冒泡
事件对象常见的属性和方法有很多,阻止事件的默认行为、阻止冒泡,比较常用。
<body>
<style>
.father {
width: 200px;
height: 200px;
background-color:red;
}
.son {
position: relative;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
width: 100px;
height: 100px;
background-color: orange;
}
</style>
<div class="father">
<div class="son">SEO</div>
<a href="www.bailong.org.cn">白龙网</a>
</div>
<script>
var father = document.querySelector('.father');
father.addEventListener('click',function(e){
//1-1返回触发事件的对象,标准
alert('father');
//4.阻止冒泡的两种方法,第一种高版本浏览器,第二种低版本浏览器
e.stopPropagation();
console.log(e.target);
})
var son = document.querySelector('.son');
son.addEventListener('click',function(e) {
//1-2返回触发事件的对象,非标准,IE6/7/8等低版本浏览器使用
alert('son');
e.stopPropagation();
e.cancelBubble;
console.log(e.srcElement);
//2.返回事件的类型,不带on,如click,mouse
console.log(e.type);
})
var a = document.querySelector('a');
a.addEventListener('click',function(e) {
//3-1.阻止事件的默认行为,如不让链接跳转,标准写法
// e.preventDefault();
//3-2阻止事件默认行为,IE6/7/8使用
// e.returnValue;
//3-3他也可以阻止事件的默认行为,但是,后面的程序会停止运行,但是该方式只限于传统的注册方式
// return false;
})
</script>
</body>
6、事件委托
不是把每个子节点都设置一个监听器,而是把监听器设置把父节点上,然后利用冒泡原理,影响每个子节点。
<body>
<ul>
<li>白龙网</li>
<li>白龙网</li>
<li>白龙网</li>
<li>白龙网</li>
<li>白龙网</li>
<li>白龙网</li>
</ul>
<script>
var ul = document.querySelector('ul');
ul.addEventListener('click',function(e) {
e.target.style.backgroundColor = '#999';
})
</script>
</body>
7、鼠标事件
(1)案例:禁止右键、禁止复制
event对象代表事件的状态,现阶段,事件对象主要是鼠标事件与键盘事件。
<body>
白龙网-从建站到SEO的在线服务平台
<script>
document.addEventListener('contextmenu',function(e) {
//1.禁止右键
e.preventDefault();
})
document.addEventListener('selectstart',function(e) {
//2.禁止复制
e.preventDefault();
})
</script>
</body>
(2)案例:获取鼠标坐标位置
<body>
<script>
document.addEventListener('click',function(e) {
//1.client,是相对于可视区浏览器的坐标位置,滚动浏览器,坐标位置不变
console.log(e.clientX);
console.log(e.clientY);
console.log('-------------------------------');
//2.page相对于文档页面的X/Y坐标
console.log(e.pageX);
console.log(e.pageY);
console.log('-------------------------------');
console.log(e.screenX);
console.log(e.screenY);
})
</script>
</body>
(3)案例:移动的天使,跟随鼠标的文字
<body>
<style>
div {
position: absolute;
width: 50px;
height: 25px;
}
</style>
<div>白龙网</div>
<script>
var div = document.querySelector('div');
//0.在整个文档区注册事件
document.addEventListener('mousemove',function(e) {
//1.获取鼠标相对页面的位置
var x = e.pageX;
var y = e.pageY;
//2.把坐标的位置赋值给绝对定位的div的top/left
div.style.left = x + 'px';
div.style.top = y + 'px';
})
</script>
</body>
8、键盘事件
键盘事件的执行顺序是onkeydown->onkeypress->onkeyup。
<script>
document.onkeydown = function() {
//1.鼠标按下
console.log('onkeydown');
//2.鼠标按下,不能识别功能键如shift,alt,箭头等。
console.log('onkeypress');
//3.鼠标松开
console.log('onkeyup');
}
</script>
案例1:判断用户按下了哪个键
<script>
document.addEventListener('keydown',function(e) {
//1.keyup、keydown可以识别功能键,但是无法区别大小写
console.log(e.keyCode);
})
document.addEventListener('keypress',function(e) {
//2.keypress可以区分大小写,但是无法识别功能键
console.log(e.keyCode);
})
document.addEventListener('keyup',function(e) {
//3.使用e.keyCode属性值、借助ASCII码判断按下了哪个键
if (e.keyCode == 65) {
console.log('你按住了:A');
} else {
console.log('按错了,没有按:A');
}
})
</script>
案例2: 模拟京东按钮输入s,搜索框自动获取焦点输入
<body>
<input type="text">
<script>
var search = document.querySelector('input')
document.addEventListener('keyup',function(e) {
// console.log(e.keyCode);使用事件对象获取按键的ASCII的值,确定按了哪个键
if (e.keyCode === 83) {
//如果按了s键,就把焦点给到search对象
search.focus();
}
})
</script>
</body>
案例3:模拟京东快递单号查询(类似放大镜功能)
这里需要注意的是,为什么这里用keyup,遭遇不用keydown/keypress。涉及两个事件类型的区别了:
keydown/keypress,是当按键按下时,已经触发了事件,但是文字还没有输入,当然内容就会显示不全了;
而keyup,是按键松开前,文字已经完成了输入,所以内容都显示出来了。
<body>
<style>
.cron {
display: none;
height: 30px;
width: 167px;
border: 1px solid #999;
font-size: 25px;
line-height: 30px;
}
</style>
<div class="search">
<div class="cron"></div>
<input type="text" placeholder="请输入关键词" class="bailong">
</div>
<script>
var cron = document.querySelector('.cron');
var bailong = document.querySelector('.bailong');
bailong.addEventListener('keyup',function() {
//判断如果没有输入内容,或者输入内容为空时,隐藏上面的盒子;有内容输入,则显示上面的盒子,并且把输入的内容赋值给上面盒子的对象
if (this.value === '') {
cron.style.display = 'none';
} else {
cron.style.display = 'block';
cron.innerHTML = this.value;
}
});
//加处加一个判断,当失去焦点的时候,隐藏上面的盒子;当获得焦点且输入内容非空时,显示上面的盒子
bailong.addEventListener('blur',function() {
cron.style.display = 'none';
});
bailong.addEventListener('focus',function() {
if(this.value != '') {
cron.style.display = 'block';
}
})
</script>
</body>
白龙网认为,对于JS事件,我们需要了解事件组成、执行;另外,对于事件注册、删除、对象、委托、流、冒泡、、类型也要熟练运用。
白龙网认为,对于JS事件,我们需要了解事件组成、执行;另外,对于事件注册、删除、对象、委托、流、冒泡、、类型也要熟练运用。