事件流
事件触发后文档的执行流程
- 捕获阶段-父到子
- 从DOM开始逐级迭代,直到找到对应的目标源(反向的冒泡阶段)
- 冒泡阶段-子到父
- 从目标源开始逐级向上传递,直到最终到DOM,此阶段所有元素都会执行该事件;如果父子都监听有相同类型的事件,点击子事件源之后父元素也会执行子元素执行的事件
DOM.addEventListener('事件',function(),true); //开启捕获阶段执行
DOM.addEventListener('事件',function(),false); //默认捕获阶段不执行
//只要事件执行,那必然有捕获阶段和冒泡阶段;即便开启捕获阶段,冒泡阶段依旧执行;
//当不开启捕获阶段时,捕获阶段依旧执行;一个事件同一时间只可以开启一个阶段
因为事件流会导致其他可能的问题,所以我们可以阻止事件冒泡或捕获
const doc = document.querySelector('div');
doc.addEventListener('click', fn1)
function fn1(e){ //e是事件执行时产生的对象
e.stopPropagation(); //语法:事件对象.stopPropagation 阻止事件冒泡
}
const link = document.querySelector('a');
link.addEventListener('click', fn2)
function fn2(e){
e.preventDefault(); //阻止元素的默认行为
}
document.addEventListener('click', fn3)
function fn3(e){
consloe.log(e.target); //输出根事件源,即目标事件源
}
on和事件事件监听的区别
- on:同类型的事件只有一个,不可以开启事件捕获
- addEventListener: 同类型的事件可以有多个,可以开启捕获
//DOM L0
const btn = documen.querySelector('.btn');
btn.onclick = function(){console.log(1)}; //绑定事件
btn.onclick = function(){console.log(2)}; //最终控制台仅输出2,前面一个事件会被后面同类型事件覆盖
//DOM L2
const btn = document.querySelector('.btn');
btn.addEventListener('click',function(){console.log('A')}); //绑定事件
btn.addEventListener('click',function(){console.log('B')});
//最终输出A,B 监听事件可以同时存在
解绑事件
//DOM L0
const btn = documen.querySelector('.btn');
btn.onclick = function(){console.log(1)};
btn.onclick = null; //将btn的click事件解除绑定
//DOM L2
const btn = document.querySelector('.btn');
btn.addEventListener('click',function(){console.log('A')}); //无法解绑,函数为匿名函数,无函数名称
btn.addEventListener('click', fn4)
function fn4(){
console.log('B')
}
//语法:事件源.removeEventListen('事件类型', 函数名)
btn.removeEventListener('click', fn4)
鼠标事件
- mouseenter、mouseleave 不支持冒泡
- mouseove、mouseout 支持冒泡
<div>
<p></p>
</div>
const p = document.querySelector('p');
const div = document.querySelector('div');
p.addEventListener('mouseenter',()=>{console.log('p')});
div.addEventListener('mouseenter',()=>{console.log('div')});
//此时我们仅点击p,控制台最终输出p
p.addEventListener('mouseover',()=>{console.log('p')});
div.addEventListener('moseover',()=>{console.log('div')});
//此时我们仅点击p,控制台最终输出p,div
事件委托
子孙元素事件委托给上级元素;原理是根据事件冒泡
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
//1.将事件给上级元素注册
//2.利用事件对象.target找到目标源
//3.利用tagName返回元素的大写标签名判断是否是我们需要的元素
const ul = document.querySelector('ul');
ul.addEventListener('click',(e)=>{
if(e.target.tagName === 'LI')e.target.style.background = '#0ff';
//判断受点击的是否是li,如果是则执行
//元素.tagName 将会返回元素的大写标签名
//div.tagName 等于DIV
})
加载事件
//语法:事件源.addEventListener('load',()=>{console.lod('加载完毕')}),等该目标资源加载完毕之后输出
//判断页面所有资源加载完毕,则给window添加load事件
window.addEventListener('load',()=>{console.log('所有资源加载完毕')});
//主要用在js文件在head中,设置window检测所有资源加载之后在执行该js
//DOM加载: DOMContentLoaded
document.addEventListener('DOMContentLoaded', ()=>{console.log('document加载完毕')});
//使document标签加载完毕即可执行,不用等待外部资源执行;DOM加载先于window加载执行
页面滚动事件
监听整个页面滚动
window.addEventListener('scroll',()=>{console.log('页面进行滚动了')});
页面尺寸事件
只要页面的尺寸发生改变,就会触发该事件
window.addEventListener('resize',()=>{console.log('页面尺寸改变了')});