目录
事件监听(绑定)
1、事件是在编程时系统内发生的动作或者发生的事情。
比如用户在网页上单击一个按钮
2、就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 绑定事件或者注册事件。
比如鼠标经过显示下拉菜单,比如点击可以播放轮播图等等
3、事件监听三要素:
-
事件源: 那个dom元素被事件触发了,要获取dom元素
-
事件类型: 用什么方式触发,比如鼠标单击 click、鼠标经过 mouseover 等
-
事件调用的函数: 要做什么事
4、事件监听语法:
元素对象.addEventListener(‘事件类型’,要执行的函数)
注意:
-
事件类型要加引号
-
函数是触发之后再去执行,每次触发都会执行一次
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>事件监听</title>
</head>
<body>
<h3>事件监听</h3>
<p id="text">为 DOM 元素添加事件监听,等待事件发生,便立即执行一个函数。</p>
<button id="btn">点击改变文字颜色</button>
<script>
// 1. 获取 button 对应的 DOM 对象
const btn = document.querySelector('#btn')
// 2. 添加事件监听
btn.addEventListener('click', function () {
console.log('等待事件被触发...')
// 改变 p 标签的文字颜色
let text = document.getElementById('text')
text.style.color = 'red'
})
// 3. 只要用户点击了按钮,事件便触发了!!!
</script>
</body>
</html>
事件监听版本
1、DOM L0
事件源.on事件 = function() { }
2、DOM L2
事件源.addEventListener(事件, 事件处理函数)
3、两种注册事件的区别
(1)传统on注册(L0)
- 同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
- 直接使用null覆盖偶就可以实现事件的解绑
- 都是冒泡阶段执行的
(2)事件监听注册(L2)
- 语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)
- 后面注册的事件不会覆盖前面注册的事件(同一个事件)
- 可以通过第三个参数去确定是在冒泡或者捕获阶段执行
- 必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
- 匿名函数无法被解绑
事件类型
一、鼠标事件:鼠标触发
1、鼠标事件是指跟鼠标操作相关的事件,如单击、双击、移动等。
2、click 鼠标点击
<script>
// 双击事件类型
btn.addEventListener('dblclick', function () {
console.log('等待事件被触发...');
// 改变 p 标签的文字颜色
const text = document.querySelector('.text')
text.style.color = 'red'
})
// 只要用户双击击了按钮,事件便触发了!!!
</script>
3、mouseenter 监听鼠标是否移入 DOM 元素
<body>
<h3>鼠标事件</h3>
<p>监听与鼠标相关的操作</p>
<hr>
<div class="box"></div>
<script>
// 需要事件监听的 DOM 元素
const box = document.querySelector('.box');
// 监听鼠标是移入当前 DOM 元素
box.addEventListener('mouseenter', function () {
// 修改文本内容
this.innerText = '鼠标移入了...';
// 修改光标的风格
this.style.cursor = 'move';
})
</script>
</body>
4、mouseleave 监听鼠标是否移出 DOM 元素
<body>
<h3>鼠标事件</h3>
<p>监听与鼠标相关的操作</p>
<hr>
<div class="box"></div>
<script>
// 需要事件监听的 DOM 元素
const box = document.querySelector('.box');
// 监听鼠标是移出当前 DOM 元素
box.addEventListener('mouseleave', function () {
// 修改文本内容
this.innerText = '鼠标移出了...';
})
</script>
</body>
5、鼠标经过事件比较:
-
mouseover 和 mouseout 会有冒泡效果
-
mouseenter 和 mouseleave 没有冒泡效果 (推荐)
二、焦点事件:表单获得光标
1、focus 获得焦点
2、blur 失去焦点
三、键盘事件:键盘触发
1、Keydown 键盘按下触发
2、Keyup 键盘抬起触发
四、文本事件 :表单输入触发
1、input 用户输入事件
事件对象
获取事件对象
1、也是个对象,这个对象里有事件触发时的相关信息
例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
2、使用场景
(1)可以判断用户按下哪个键,比如按下回车键可以发布新闻
(2)可以判断鼠标点击了哪个元素,从而做相应的操作
3、语法:
元素.addEventListener(‘click’,function(e){
//执行代码
})
(1)在事件绑定的回调函数的第一个参数就是事件对象
(2)一般命名为event、ev、e
<body>
<h3>事件对象</h3>
<p>任意事件类型被触发时与事件相关的信息会被以对象的形式记录下来,我们称这个对象为事件对象。</p>
<hr>
<div class="box"></div>
<script>
// 获取 .box 元素
const box = document.querySelector('.box')
// 添加事件监听
box.addEventListener('click', function (e) {
console.log('任意事件类型被触发后,相关信息会以对象形式被记录下来...');
// 事件回调函数的第1个参数即所谓的事件对象
console.log(e)
})
</script>
</body>
事件对象常用属性
1、 type
获取当前的事件类型
2、clientX/clientY
获取光标相对于浏览器可见窗口左上角的位置
3、offsetX/offsetY
获取光标相对于当前DOM元素左上角的位置
4、key
用户按下的键盘键的值
现在不提倡使用key
5、target
用于表示触发事件的目标元素。
环境对象
1、环境对象:指的是函数内部特殊的变量 this ,它代表着当前函数运行时所处的环境
2、作用:弄清楚this的指向,可以让我们代码更简洁
-
函数的调用方式不同,this 指代的对象也不同
-
【谁调用, this 就是谁】 是判断 this 指向的粗略规则
3、直接调用函数,其实相当于是 window.函数,所以 this 指代 window
<script>
// 声明函数
function sayHi() {
// this 是一个变量
console.log(this);
}
// 声明一个对象
let user = {
name: '张三',
sayHi: sayHi // 此处把 sayHi 函数,赋值给 sayHi 属性
}
let person = {
name: '李四',
sayHi: sayHi
}
// 直接调用
sayHi() // window
window.sayHi() // window
// 做为对象方法调用
user.sayHi()// user
person.sayHi()// person
</script>
回调函数
1、把函数当做另外一个函数的参数传递,这个函数就叫回调函数
2、回调函数本质还是函数,只不过把它当成参数使用
3、使用匿名函数做为回调函数比较常见
<script>
// 声明 foo 函数
function foo(arg) {
console.log(arg);
}
// 普通的值做为参数
foo(10);
foo('hello world!');
foo(['html', 'css', 'javascript']);
function bar() {
console.log('函数也能当参数...');
}
// 函数也可以做为参数!!!!
foo(bar);
</script>
事件流
1、事件流指的是事件完整执行过程中的流动路径
2、事件流经过的2个阶段 :捕获阶段、冒泡阶段
(1)简单来说:捕获阶段是 从父到子 冒泡阶段是从子到父
(2)实际工作都是使用事件冒泡为主
事件捕获
1、事件捕获概念:从DOM的根元素开始去执行对应的事件 (从外到里)
2、事件捕获需要写对应代码才能看到效果
代码:
DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)
3、说明:
(1)addEventListener第三个参数传入 true 代表是捕获阶段触发(很少使用)
(2)若传入false代表冒泡阶段触发,默认就是false
(3)若是用 L0 事件监听,则只有冒泡阶段,没有捕获
事件冒泡
1、事件冒泡概念:当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡
2、简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的 同名事件
3、事件冒泡是默认存在的
4、L2事件监听第三个参数是 false,或者默认都是冒泡
<body>
<h3>事件流</h3>
<p>事件流是事件在执行时的底层机制,主要体现在父子盒子之间事件的执行上。</p>
<div class="outer">
<div class="inner">
<div class="child"></div>
</div>
</div>
<script>
// 获取嵌套的3个节点
const outer = document.querySelector('.outer');
const inner = document.querySelector('.inner');
const child = document.querySelector('.child');
// html 元素添加事件
document.documentElement.addEventListener('click', function () {
console.log('html...')
})
// body 元素添加事件
document.body.addEventListener('click', function () {
console.log('body...')
})
// 外层的盒子添加事件
outer.addEventListener('click', function () {
console.log('outer...')
})
// 中间的盒子添加事件
outer.addEventListener('click', function () {
console.log('inner...')
})
// 内层的盒子添加事件
outer.addEventListener('click', function () {
console.log('child...')
})
</script>
</body>
执行上述代码后发现,当单击事件触发时,其祖先元素的单击事件也【相继触发】
结合事件流的特征,我们知道当某个元素的事件被触发时,事件总是会先经过其祖先才能到达当前元素,然后再由当前元素向祖先传递,事件在流动的过程中遇到相同的事件便会被触发。
再来关注一个细节就是事件相继触发的【执行顺序】,事件的执行顺序是可控制的,即可以在捕获阶段被执行,也可以在冒泡阶段被执行。
如果事件是在冒泡阶段执行的,我们称为冒泡模式,它会先执行子盒子事件再去执行父盒子事件,默认是冒泡模式。
如果事件是在捕获阶段执行的,我们称为捕获模式,它会先执行父盒子事件再去执行子盒子事件。
阻止冒泡
1、因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素
2、若想把事件就限制在当前元素内,就需要阻止事件冒泡
3、阻止事件冒泡需要拿到事件对象
4、阻止事件冒泡语法:
事件对象.stopPropagation()
注意:此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效
5、我们某些情况下需要阻止默认行为的发生,比如 阻止 链接的跳转,表单域跳转
阻止默认行为语法:e.preventDefault()
<body>
<h3>阻止冒泡</h3>
<p>阻止冒泡是指阻断事件的流动,保证事件只在当前元素被执行,而不再去影响到其对应的祖先元素。</p>
<div class="outer">
<div class="inner">
<div class="child"></div>
</div>
</div>
<script>
// 获取嵌套的3个节点
const outer = document.querySelector('.outer')
const inner = document.querySelector('.inner')
const child = document.querySelector('.child')
// 外层的盒子
outer.addEventListener('click', function () {
console.log('outer...')
})
// 中间的盒子
inner.addEventListener('click', function (ev) {
console.log('inner...')
// 阻止事件冒泡
ev.stopPropagation()
})
// 内层的盒子
child.addEventListener('click', function (ev) {
console.log('child...')
// 借助事件对象,阻止事件向上冒泡
ev.stopPropagation()
})
</script>
</body>
结论:事件对象中的
ev.stopPropagation
方法,专门用来阻止事件冒泡。
解绑事件
1、on事件方式,直接使用null覆盖偶就可以实现事件的解绑
//绑定事件
Btn.οnclick=function(){
alert(“点击”)
}
//解绑事件
Btn.οnclick=null
2、addEventListener方式,必须使用:
removeEventListener(事件类型, 事件处理函数, [获取捕获或者冒泡阶段])
注意:匿名函数无法被解绑
Function fn(){
Alert(“点击了”)
}
//绑定事件
Btn.addEventListerner(‘click’,fn)
//解绑事件
Btn.removeEventListener(‘click’,fn)
事件委托
1、事件委托是利用事件流的特征解决一些开发需求的知识技巧
-
优点:减少注册次数,可以提高程序性能
-
原理:事件委托其实是利用事件冒泡的特点。
2、给父元素注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件。
3、实现:事件对象.target. tagName 可以获得真正触发事件的元素。
其他事件
页面加载事件
加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件
1、load 事件
-
监听整个页面资源给 window 加
-
监听页面所有资源加载完毕:给 window 添加 load 事件
Window.addEventListener(‘load’,function(){ //执行操作 })
- 注意:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定load事件
2、DOMContentLoaded事件
-
给 document 加
-
无需等待样式表、图像等完全加载
-
当初始的HTML文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像等完全加载
-
事件名:DOMContentLoaded
-
监听页面DOM加载完毕:给 document 添加 DOMContentLoaded 事件
document.addEventListener(‘DOMContentLoaded’,function(){//执行操作})
元素滚动事件
-
滚动条在滚动的时候持续触发的事件
-
使用场合:很多网页需要检测用户把页面滚动到某个区域后做一些处理, 比如固定导航栏,比如返回顶部
-
事件名:scroll
-
监听整个页面滚动:给 window 或 document 添加 scroll 事件
//页面滚动事件
Window.addEventListener(‘scroll’,function(){
//执行操作
})
- 监听某个元素的内部滚动直接给某个元素加即可
1、页面滚动事件-获取位置
(1)scrollLeft和scrollTop (属性)
-
获取被卷去的大小
-
获取元素内容往左、往上滚出去看不到的距离
-
可以读取,也可以修改(赋值)
(2)尽量在scroll事件里面获取被卷去的距离
Div.addEventListener(‘scroll’,function(){
Console.log(this.scrollTop)
})
(3)开发中,我们经常检测页面滚动的距离,比如页面滚动100像素,就可以显示一个元素,或者固定一个元素
//页面滚动事件
Window.addEventListener(‘scroll’,function(){
//执行操作
//document.documentElement 是html元素获取方式
Const n=document.documentElement .scrollTop
Console.log(n)
})
注意事项:
document.documentElement HTML 文档返回对象为HTML元素
2、页面滚动事件-滚动到指定的坐标
(1)、scrollTo() 方法可把内容滚动到指定的坐标
(2)、语法:元素.scrollTo(x, y)
例如:
//让页面滚动到Y轴1000像素的位置
Window.scrollTop(0,1000)
页面尺寸事件
1、会在窗口尺寸改变的时候触发事件:
-
resize
Window.addEventListener(‘resize’,function(){ //执行代码 })
-
检测屏幕宽度:
Window.addEventListener(‘resize’,function(){ Let w=document.doucumentElement.clientWidth Console.log(w) })
2、获取宽高:
-
获取元素的可见部分宽高(不包含边框,margin,滚动条等)
-
clientWidth和clientHeight
元素尺寸与位置
使用场景:
-
前面案例滚动多少距离,都是我们自己算的,最好是页面滚动到某个元素,就可以做某些事。
-
简单说,就是通过js的方式,得到元素在页面中的位置
-
这样我们可以做,页面滚动到这个位置,就可以做某些操作,省去计算了
1、元素尺寸于位置-尺寸
(1)获取宽高:
-
获取元素的自身宽高、包含元素自身设置的宽高、padding、border
-
offsetWidth和offsetHeight
-
获取出来的是数值,方便计算
-
注意:获取的是可视宽高, 如果盒子是隐藏的,获取的结果是0
(2)获取位置:
-
获取元素距离自己定位父级元素的左、上距离
-
offsetLeft和offsetTop 注意是只读属性
总结: