事件对象
含义
当事件触发的时候 ,会产生对象,记录一些事件和有关信息
获取
事件处理函数中,形参就是事件对象
document.addEventListener('click' , function(e) {
// e就是事件对象
// 关于事件对象,如果需要使用,就写上形参e,不需要使用,可以忽略不写
console.log(e)
})
事件对象常用属性
1. pageX / pageY
获取鼠标的位置信息
pageX :距离页面左侧的水平距离
pageY: 距离页面上侧的垂直距离
示例:
document.addEventListener('click' , function(e) {
console.log(e.pageX , e.pageY)
})
效果:
2. key
获取用户按键信息
用户按下键盘的值
示例:
document.addEventListener('keydown' , function(e) {
console.log('键盘按下' , e.key)
// keydown按下不松手会频繁触发事件,所以一般使用keyup事件
})
document.addEventListener('keyup' , function(e) {
console.log('键盘弹起' , e.key)
})
事件流
指的是事件完整执行过程中的流动路径
两个阶段:先捕获在冒泡
捕获阶段是 从父到子
冒泡阶段是 从子到父
事件冒泡 🔺
当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡
- 简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件
- 事件冒泡是默认存在的,事件冒泡和元素是否有注册上事件是无关的。
// 演示事件冒泡
document.addEventListener('click' , function(){
console.log('我是document')
})
document.body.addEventListener('click' , function() {
console.log('我是body')
})
fa.addEventListener('click' , function() {
console.log('我是father')
})
son.addEventListener('click' , function() {
console.log('我是son')
})
点击 son:
注意:
鼠标经过事件:
mouseover
和mouseout
会有冒泡效果mouseenter
和mouseleave
没有冒泡效果 (推荐)
事件捕获
概念:
从DOM的根元素开始去执行对应的事件。
addEventListener第三个参数传入true代表是捕获阶段触发
- 若传入false代表冒泡阶段触发,默认就是false
- 若是用 L0 事件监听,则只有冒泡阶段,没有捕获
document.addEventListener('click' , function(){
console.log('我是document')
},true)
document.body.addEventListener('click' , function() {
console.log('我是body')
},true)
fa.addEventListener('click' , function() {
console.log('我是father')
},true)
son.addEventListener('click' , function() {
console.log('我是son')
},true)
图示 :事件捕获 事件冒泡
阻止事件流动
语法
事件对象.stopPropagation()
此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效
let fa = document.querySelector('.father')
let son = document.querySelector('.son')
son.addEventListener('click', function (e) {
console.log('is son')
//阻止事件流,,直接在father上被掐断了,也不会冒到body document。。。
e.stopPropagation()
})
fa.addEventListener('click', function (e) {
console.log('is father')
})
阻止浏览器的默认行为
所谓阻止默认行为,比如链接点击不跳转,表单域不提交
语法:
e.preventDefault()
例子
<a href="http://www.baidu.com">跳转到百度</a>
<script>
// 阻止浏览器的默认行为
// 事件对象e有 方法可以来阻止浏览器的默认行为
let a = document.querySelector('a')
a.addEventListener('click', function (e) {
e.preventDefault()
alert('哈哈,被点击了,但是没跳转~')
})
</script>
事件委托
优点:
- 给父级元素 注册事件(可以提高性能)
- 给动态新创建的元素注册事件
原理:
事件冒泡,点击子元素时,冒泡冒到了父元素,所以给父元素注册的事件,子元素也能触发。
实现:
事件对象.target
可以获得真正触发事件的元素
使用tagName
属性可以得到元素名(注意得到的元素名是大写)
案例:点击p元素 出现弹框
- 传统做法
let box = document.querySelector(".box");
let ps = document.querySelectorAll(".box p");
let create = document.querySelector(".create");
// 常规做法:找到所有的p,给所有的p注册click
// 缺点:1. 有较大性能消耗 2. 无法给动态新创建的元素注册事件(触发事件)
for (let i = 0; i < ps.length; i++) {
ps[i].onclick = function () {
alert("哈哈")
}
}
// 点击按钮,新建p添加到div中
create.addEventListener('click', function () {
let newP = document.createElement('p')
newP.innerHTML = '新建的p'
box.appendChild(newP)
})
- 事件委托
// 事件委托做法:
// 做法:把事件委托注册给父元素(祖先元素)
// 优点:可以提高性能,给动态新创建的元素注册事件
// 原理:事件冒泡
box.addEventListener('click' , function(e) {
//事件对象.target 可以获得真正触发事件的元素,使用tagName可以得到元素名(注意是大写)
console.log(e.target , e.target.tagName)
if(e.target.tagName === 'P') alert('p被点击啦~')
})
两种注册事件的区别
传统on注册(L0)
- 同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
- 直接使用null覆盖就可以实现事件的解绑
- 都是冒泡阶段执行的
// 需求:按钮的点击事件只能触发一次
// 解绑事件
// 解绑语法: 元素.onclick = null
btn.onclick = function() {
console.log('我被点击啦')
// 解绑按钮注册的点击事件
btn.onclick = null
}
事件监听注册(L2)
语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)
- 后面注册的事件不会覆盖前面注册的事件(同一个事件)
- 可以通过第三个参数去确定是在冒泡或者捕获阶段执行
- 必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
- 匿名函数无法被解绑
// addEventListener 注册的事件如何解绑 ==> 需要使用removeEventListener来进行解绑
// **匿名函数无法解绑**
// 所以 以下注册事件无法解绑
/* btn.addEventListener('click' , function() {
})
btn.removeEventListener('click' , function() {
}) */
// **正确解绑方法 把匿名函数写成具名函数**
function fn() {
console.log('我点击了')
// 解绑 效果是只能点击一次
btn.removeEventListener('click' , fn)
}
btn.addEventListener('click' , fn)
滚动事件
当页面进行滚动时触发的事件
事件名:
scroll
给 window 或 document 添加 scroll 事件
例如:监听整个页面滚动
window.addEventListener('scroll' , function() {
})
加载事件
事件名:load
加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件。
给window添加
不仅可以监听整个页面资源加载完毕,也可以针对某个资源绑定load事件
例如:监听页面所有资源加载完毕:
window.addEventListener('load' , function() {
})
事件名:DOMContentLoaded
当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、 图像等完全加载
给document添加
例如:监听页面DOM加载完毕
document.addEventListener('DOMContentLoaded' , function() {
})
元素大小和位置
scroll 家族
scrollWidth 和scrollHeight
获取元素内容的总宽高(不包含滚动条)
只读属性
scrollLeft 和 scrollTop
获取元素内容向左滚,向上滚出去看不到的距离。
可以修改
获取页面的滚动卷曲距离
document.documentElement.scrollTop
window.addEventListener('scroll' , function() {
let num = document.documentElement.scrollTop
console.log(num)
})
offset家族
offsetWidth 和 offsetHeight (只读)
获取元素的真实宽高、包含元素自身设置的宽高、padding、border
offsetLeft 和 offsetTop(只读)
获取元素距离自己定位父级的左、上距离
offsetTop和offsetLeft 得到位置以带有定位的父级为准,如果都没有则以 文档左上角 为准
client家族
clientWidth和clientHeight (只读)
获取元素的可见部分宽高(不包含边框,滚动条等)
clientLeft和clientTop (只读)
获取左边框和上边框宽度
resize 事件
会在窗口尺寸改变的时候触发事件
// resize事件 : 当浏览器大小发生改变的时候会触发该事件 ==> 可以用于获取页面可视区大小
window.addEventListener('resize' , function () {
let w = document.documentElement.clientWidth
console.log(w)
})
给页面注册事件,到底给window还是document
给window注册的事件
-
load 加载完成
-
scroll 滚动
-
resize 窗口大小发生改变