上了生活的贼船 就做快乐的海盗
目录
一、 什么是js事件
事件是指在编程时系统内发生的动作或者发生的事情
比如用户在网页上单击一个按钮
二、基本事件类型
- 鼠标事件: click 点击 mouseenter 鼠标经过 mouseleave 鼠标离开
- 焦点事件:focus 获得焦点 blur失去焦点
- 键盘事件:keydown 键盘按下(一直按住不放则按秒计算事件) keyup 键盘抬起(抬起那一下触发)
- 文本事件:input 用户输入(按个计算事件)
三、事件监听
1.什么是事件监听?
就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称之为 绑定事件或者注册事件
比如鼠标经过下拉菜单,比如点击可以播放轮播图等等
2.事件监听的三要素
- 事件源:哪个dom对象被事件触发了,要获取dom对象
- 事件类型:用什么方式触发,比如鼠标点击click 鼠标经过 mouseover 等
- 事件触发后调用的函数:要做什么事
3.事件监听的使用
格式:
对象.addEventListener('事件类型' , 要执行的函数)
补充:
老版本的事件监听
缺点,同一个事件只能进行一个监听,多了会被覆盖
对象名.on事件类型 = 要执行的函数
案例练习:鼠标事件
需求:
1.鼠标移动到按钮上提示进入按钮,离开按钮提示离开按钮
2点击按钮,弹出事件监听四个字
<button>按钮</button>
<script>
const buttonObject = document.querySelector('button')
buttonObject.addEventListener('mouseenter',function(){
alert('进入按钮')
})
buttonObject.addEventListener('mouseleave', function(){
alert('离开按钮')
})
buttonObject.addEventListener('click' , function(){
alert("事件监听1")
})
buttonObject.addEventListener('click' , function(){
alert("事件监听2")
})
//老版本
const dx = document.querySelector('button')
dx.onclick = function(){
alert("事件监听1")
}
dx.onclick = function(){
alert("事件监听2")
}
//老版本缺陷:同一个事件(click)会被覆盖,事件监听1被事件监听2覆盖
dx.onmouseenter = function(){
alert('进入按钮')
}
dx.onmouseleave = function(){
alert('离开按钮')
}
</script>
案例练习:焦点事件
需求:
点击搜索框,获得焦点,出现下拉列表
点击搜索框外面,失去焦点,下拉列表隐藏
<style>
.mi{
display=none;
}
</style>
<input type="text" placeholder="小米笔记本" class="i">
<ul class="mi">
<li>手机
<li>电视
</ul>
<script>
const inputObject = document.querySelector('.i')
const ulliObject = document.querySelector('.mi')
inputObject.addEventlistener('focus', c)
function c(){
ulliObject.style.display='block'
}
inputObject.addEventlistener('blur',function(){
ulliObject.style.display='none'
})
</script>
案例练习:键盘事件
需求:输入框添加键盘事件监听
1.键盘按下提示,keydowun
2.键盘抬起提示,keyup
<input type="text" name="" id="">
<script>
const inputObject = document.querySelector('input')
inputObject.addEventListener('keydown',function(){
console.log('键盘按下')
})
inputObject.addEventListener('keyup',function(){
console.log('键盘抬起')
})
</script>
案例练习:文本事件
需求:
边输入边记录字数
温馨提示:获取input输入框里面value属性的长度 对象.value.length
<input type="text" class="sr">
<span class="to">0/200字</span>
<script>
const inputObject = document.querySeletor('.sr')
const spanObject = document.querySeletor('.to')
inputObject.addEventListener('input',function(){
spanObject.innerHTML =`${inputObject.value.length}/200字`
})
</script>
四、事件对象
事件触发后自动生成一个对象,该对象里面包含了这次事件的一些具体信息。我们将该对象称之为事件对象
如何获取事件对象?
事件监听执行是·回调函数的第一个参数就是事件对象,通常事件对象名可以自定义
常用事件对象名:e 、evt 、event
事件对象常用的一些属性:
type
记录本次事件类型
clientX/clientY
浏览器可视化界面的(X,Y)坐标位置
offsetX/offsetY
事件源范围盒子界面的(X,Y)坐标位置
key/code 老版本叫keycode,不提倡使用,马上要删除了
按下的键盘的键盘值
<input type="text" name="" id="">
<script>
const buttonObject = document.querySelector('input')
//为什么用keyup,因为keydown一直按住不放,则一直触发
//而keyup只有抬起一下,也只有那一下,适合开发使用
buttonObject.addEventListener('keyup',function(e){
console.log(e)
console.log(e.type)
console.log(e.clientX,e.clientY)
if(e.key === 'Enter'){
console.log(e.key)
}else{
console.log('不是Enter')
}
})
</script>
案例练习:发布评论
需求:
1.记录输入字数
2.按下回车,发布评论
3.点击批量进行评论
分析:
用到文本和鼠标事件
用到键盘事件并指定回车键
让评论信息模块显示,把拿到的数据渲染到对应标签内部,并清空文本域
知识补充:字符串的属性方法.trim()
.trim() 是string字符串提供的一个属性方法
作用:
用于清除字符串左右两边的空字符串
温馨提示:只清除字符串左右两边,中间的不清除
如果是多个空字符串,则清空为一个空字符串
let a = ' a aa '
let b = ' '
a.trim()
b.trim()
console.log(a)
//'a aa'
console.log(b)
//''
代码实现
<input type="text" name="" id="" placeholder="发布评论">
<button>发布</button>
<br>
<span id="a">0/200字</span>
<br>
<span id="b"></span>
<script>
//获取dom对象
const inputObject = document.querySelector('input')
const buttonObject = document.querySelector('button')
const span1Object = document.querySelector('#a')
const span2Object = document.querySelector('#b')
//记录字数
inputObject.addEventListener('input',function(){
span1Object.innerHTML = `${inputObject.value.length}/200字`
})
//点击发布
buttonObject.addEventListener('click',function(){
if(inputObject.value.trim() !== ''){
span2Object.innerHTML = `发布的评论为${inputObject.value}`
}
//清空字数和输入框内容
inputObject.value = ''
span1Object.innerHTML = `${inputObject.value.length}/200字`
})
//回车发布
inputObject.addEventListener('keyup',function(e){
console.log(e.type)
if(e.key === 'Enter'){
if(inputObject.value.trim() !== ''){
span2Object.innerHTML = `发布的评论为${inputObject.value}`
}
//清空字数和输入框内容
inputObject.value = ''
span1Object.innerHTML = `${inputObject.value.length}/200字`
}
})
</script>
五、环境对象this
环境对象是指函数内部的特殊变量this,它代表着当前函数运行时所处的环境
作用:
弄清楚this指向,可以让我们代码更简洁
调用函数的方式不同,this所指向的对象也不同
粗略判断this指向的规则:
谁调用,this就指向谁
//普通函数
function fn() {
console.log(this)//指向window对象
}
fn()//相当于window.fn()
//一些特殊函数--例如监听器函数
<button>提交</button>
const buttonObject = document.querySelector('button')
buttonObject.addEventListener('click',function(){
console.log()//指向buttonObject对象
this.style.color = 'red'
})
六、回调函数
回调函数是指:当一个函数作为参数来传递给另外一个函数的时候,那么这个函数就是回调函数
简单理解:
如果函数A作为参数传递给函数B时,我们就称函数A为回调函数
<div>回调函数</div>
<script>
function fn(){
console.log('我是回调函数');
}
const divObject = document.querySelector('div')
divObject.addEventListener('mouseenter', fn) //fn是事件监听函数的回调函数
divObject.setInterval(function(){
console.log('我是回调函数')
}, 1000) //匿名函数function是间歇函数的回调函数
</script>
七、事件流
事件流是指事件完整执行过程中的流动路径
事件流分为两个阶段
- 捕获阶段
- 冒泡阶段
老版本事件监听只有事件冒泡,没有捕获
新版本事件监听既有捕获又有冒泡,是通过事件监听函数第三个参数来控制的
1.事件捕获(了解)
事件捕获的概念:从DOM根元素开始去执行对应的事件(从外到里)
代码
DOM.addEventListener(事件类型,事件执行的函数,是否使用捕获机制true和false)
事件捕获机制默认是不写的,那么就默认为false不使用事件捕获机制
<style>
.father{
height: 100px;
width: 100px;
background-color: red;
}
.son{
height: 50px;
width: 50px;
background-color:black;
}
</style>
<body>
<div class="father">
<div class="son">
</div>
</div>
</body>
<script>
const div1Object = document.querySelector('.father')
const div2Object = document.querySelector('.son')
document.addEventListener('click', function () {
alert('祖父')
}, true)
div1Object.addEventListener('click', function () {
alert('爸爸')
}, true)
div2Object.addEventListener('click', function () {
alert('儿子')
}, true)
</script>
2.事件冒泡
事件冒泡的概念:当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程称之为事件冒泡
简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的 同名事件
温馨提示:由于事件监听捕获机制默认关闭为false,那么就代表默认开启了事件冒泡,所以说事件冒泡是默认存在的,是必然会发生的
<style>
.father{
height: 100px;
width: 100px;
background-color: red;
}
.son{
height: 50px;
width: 50px;
background-color:black;
}
</style>
<body>
<div class="father">
<div class="son">
</div>
</div>
</body>
<script>
const div1Object = document.querySelector('.father')
const div2Object = document.querySelector('.son')
document.addEventListener('click', function () {
alert('祖父')
})
div1Object.addEventListener('click', function () {
alert('爸爸')
})
div2Object.addEventListener('click', function () {
alert('儿子')
})
</script>
3.阻止事件流(冒泡、捕获)
由于事件冒泡是默认存在的,会影响到我们开发
因此若想把事件限制在当前元素内,就要阻止事件冒泡
阻止事件冒泡的步骤
1.拿到该元素的事件对象
2.使用对象方法 stopPropagation()
温馨提示:此方法不但可以阻止事件冒泡,也可以阻止事件捕获
该方法写到哪里,那么就不会往下发生事件冒泡
<style>
.father{
height: 100px;
width: 100px;
background-color: red;
}
.son{
height: 50px;
width: 50px;
background-color:black;
}
</style>
<body>
<div class="father">
<div class="son">
</div>
</div>
</body>
<script>
const div1Object = document.querySelector('.father')
const div2Object = document.querySelector('.son')
document.addEventListener('click', function () {
alert('祖父')
})
div1Object.addEventListener('click', function () {
alert('爸爸')
})
div2Object.addEventListener('click', function (e) {
alert('儿子')
e.stopPropagation()
})
</script>
八、事件解绑
将设置好的事件监听进行解绑(取消监听)
格式:
对象名.removeEventListener(事件类型, 事件处理函数, [获取捕获或者冒泡阶段])
老版本
对象名.on事件类型 = null
为什么老版本这么方便?因为不存在重复类型事件,它本身会覆盖重复类型事件,而新版本不会覆盖因此相同事件类型很多,因此要具体表示删哪一个
温馨提示:新版本事件监听里面为匿名函数,则该事件监听无法解绑
<ul>
</ul>
<script>
const ulObject = document.querySelector('ul')
//新版本
function fn() {
alert('事件解绑')}
ulObject.addEventListener('click', fn)
ulObject.removeEventListener('click',fn)
//老版本
ulObject.onclick = null
</script>
九、事件委托
事件冒泡有好有坏,我们也可以充分利用事件冒泡的特点来使用它
事件委托是利用事件 流的特征解决一些开发需求的知识技巧
优点:减少设置监听次数,可以提高性能
原理:事件委托依靠事件冒泡阶段由子到父的特点
给父元素设置事件监听,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件
<body>
<ul><!-- 快捷键生成ul和li -->
<!-- ul>li{内容} * 个数 -->
<li>第1个孩子</li>
<li>第2个孩子</li>
<li>第3个孩子</li>
<li>第4个孩子</li>
<li>第5个孩子</li>
<p>这个不能变色</p>
</ul>
</body>
<script>
const ulObject = document.querySelector('ul')
ulObject.addEventListener('click', function (e){
//拿到所点击的标签的对象e.target//本质上就是ul子的的事件对象
//this.style.color='red' 这个是整个ul变成红色
console.log(e)
console.log(e.target)
console.dir(e.target)//console.dir()打印对象
//target对象里面有tagName属性,该属性是这个标签名
if(e.target.tagName === 'LI'){
e.target.style.color='red'
}
})
</script>
知识补充 :通过父事件对象可以获取触发到子事件的子事件对象。
格式:父事件对象.target
获取对应标签名属性: tagName
十、对事件的深入理解
每一个dom对象的元素都有事件,例如div、button、p等等所有html标签,他们的事件也会触发,只有我们对它进行事件监听(注册事件)后才会执行我们监听所定义的函数,就是进行一系列操作
这也就是为什么会出现事件流的原因
该事件的对象里面会保存它对象内的事件对象,也就是父事件对象里面具有子事件对象的信息可以通过 父事件对象.target 来获取当前所触发的子事件冒泡到父事件对象的子对象,子对象里面包含了自己的事件信息
十一、一些其他的事件类型
除了基本事件类型还有其他的事件类型
- 提交事件
- 页面加载事件
- 元素滚动事件
- 页面尺寸事件
1.提交事件类型
提交事件类型:submit
针对于表单的 submit操作的事件类型
可以对触发submit进行监听操作
2.加载事件类型
页面加载事件分为两种
- load
- DOMContentLoaded
2.1 加载事件---load
事件名:load
概念:当指定元素加载完后执行该事件,可以对其进行监听,触发该事件后做一些操作
通常针对于window使用,当然也可以针对某个图片、视频等等,按照原理来设定即可
监听页面所有资源加载完毕
-给window加load事件格式:window.addEventListener('load', function() { 执行的操作 })
页面-加载外部资源(图片、外联CSS、外联JS等)加载完毕时所触发的事件
给window添加load事件的作用:
有些时候需要等待页面资源加载完再做一些事情
把喜欢把js代码写在body标签上面的人解决dom元素找不到的情况
给图片加load事件格式:img.addEventListener('load', function() { 执行的操作 })
等待图片加载完毕后触发该事件,执行回调函数
给img添加load事件的作用:
等待图片加载完再执行关于图片的一系列操作,免得图片还没加载完就乱操作的
温馨提示:还有一些其他的不仅限于这两个,搞清楚原理即可广泛使用
//问题代码
<script>
const buttonObject = document.querySelector('button')
buttonObject.addEventListener('click', function () {
alert('页面获取不到dom')
})
</script>
<body>
<button>点击</button>
</body>
//解决代码,等待页面全部加载完毕再加载和执行回调函数
<script>
window.addEventListener('load', function () {
const buttonObject = document.querySelector('button')
buttonObject.addEventListener('click', function () {
alert('页面加载完执行')
})
})
</script>
<body>
<button>点击</button>
</body>
2.2 加载事件---DOMContentLoaded
事件名:DOMContentLoaded
概念:当初始HTML标签完全被加载完毕和解析完成后,DOMContentLoaded事件被触发 完 ,而无需等待样式列表、图片完全加载
单独针对于document使用
监听HTML资源加载完毕
-给document加DOMContentLoaded事件格式:document.addEventListener('DOMContentLoaded', function() { 执行的操作 })
作用:
可以让很多网速慢的同志一些样式和图片视频还没加载出来,就可以提前进行js交互
3.滚动事件
事件名:scroll
概念:滚动条在滚动的时候持续触发的事件,开发中常用于滚动到某一地方的时候做一些操作,例如导航栏
scorll的理解:谁在滚动?如果是页面那就是HTML在滚动,如果是div,那就是div里面的内容在滚动等等
常用于监听整个页面滚动:
window.addEventListener('scroll', function() { 执行的操作 })
获取html对象:
document.documentElement
也可以用于监听div内容滚动:
divdom对象.addEventListener('scroll', function() { 执行的操作 })
温馨提示:还有一些其他的不仅限于这两个,搞清楚原理即可广泛使用
dom对象的有关scroll的属性
- 对象名.scrollTop属性:获取被卷去顶部的长度
- 对象名.scrollLeft属性:获取被卷去左边的长度
该属性是可以读改的
dom对象有关的属性方法:
对象名.scrollTo(x,y) : 自动滚动到该坐标位置
<style>
body {
height: 600px;
}
div {
height: 100px;
width: 100px;
border: 1px solid #000;
overflow: scroll;
}
</style>
<body>
<div>
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
</div>
</body>
<script>
const divObjet = document.querySelector('div')
divObjet.addEventListener('scroll', function () {
console.log(divObjet.scrollTop)
})
</script>
<style>
body {
height: 600px;
}
div {
display: none;
height: 100px;
width: 100px;
border: 1px solid #000;
overflow: scroll;
}
</style>
<body>
<div>
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
阿啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
</div>
</body>
<script>
const divObjet = document.querySelector('div')
divObjet.addEventListener('scroll', function () {
console.log(divObjet.scrollTop)
})
//只能获取开始那一次的长度
document.documentElement.scrollTop
//对scrollTop属性的修改
document.documentElement.scrollTop = 300
window.addEventListener('scroll', function () {
//长度必须写在里面,这样才能随着滚动事件的监听,获取的长度也随着改变
//也就是获取最新信息
console.log(document.documentElement.scrollTop)
if(document.documentElement.scrollTop >= 350){
divObjet.style.display = 'block'
}
})
</script>
案例练习:小兔鲜显示导航栏和返回顶部
需求:
当页面滚动大于100px的距离的时候,就显示侧边栏,否则隐藏侧边栏
<style>
body {
height: 1000px;
}
ul {
opacity: 0;
height: 100px;
width: 40px;
}
li {
list-style-type: none;
border-top: 1px solid #000;
}
li:first-child {
border-top: 0px;
}
</style>
<body>
<ul>
<li>新鲜好物</li>
<li>人气推荐</li>
<li>热门品牌</li>
<li>最新专题</li>
<li class="back">返回顶部</li>
</ul>
</body>
<script>
const ulObject = document.querySelector('ul')
const fiveLiObject = document.querySelector('.back')
//对页面滚动事件监听
window.addEventListener('scroll', function () {
//获取被卷去的头部
const n = document.documentElement.scrollTop
/*
low写法
if(n > 300){
ulObject.style.opacity = 1
}else{
ulObject.style.opacity = 0
}
*/
//好写法
ulObject.style.opacity = n > 100 ? 1 : 0
})
fiveLiObject.addEventListener('click', function () {
//利用scrollTop属性的读改性
document.documentElement.scrollTop = 0
//采用scrollTo()属性方法
document.documentElement.scrollTo(0, 0)
})
</script>
4.尺寸事件
事件名:resize
概念:有尺寸发生改变的时候就会触发该事件
常用于监听整个页面尺寸:
window.addEventListener('resize', function() { 执行的操作 })
也可以用于监听文本域的尺寸:
textareadom对象.addEventListener('resize', function() { 执行的操作 })
温馨提示:还有一些其他的不仅限于这两个,搞清楚原理即可广泛使用
dom对象的有关resize的属性:
- 对象名.clientWidth : 获取该对象当前可见部分尺寸的宽
- 对象名.clientHeight :获取该对象当前可见部分尺寸的高
- 对象名.clientTop:获取该对象内容到文档顶部的高度
- 对象名.clientLeft:获取该对象内容到文档左边的长度
英语client:客户、客户端 发音: c来恩t
- 对象名.offsetWidth:获取该对象当前可见部分尺寸的宽
- 对象名.offsetHeight:获取该对象当前可见部分尺寸的高
- 对象名.offsetTop:获取该对象内容到文档顶部的高度
- 对象名.offsetLeft:获取该对象内容到文档左边的长度
温馨提示:offset受父的影响,导致它变成该对象到父对象的距离
offset和client不同的地方是:offset包含了盒子padding和border,client不包含
温馨提示:两者都是只读不改
案例练习:仿京东滑动
需求:
当页面滚动到秒杀模块,导航栏自动滑入,否则滑出
分析:
1.用到页面滚动事件
2.检测页面滚动大于等于秒杀模块的位置则滑入,否则滑出
3.主要移动的是秒杀模块顶部位置
<style>
body{
height: 600px;
}
.header {
position: fixed;
top: -80px;
left: 0;
width: 100%;
height: 80px;
background-color: purple;
}
.sk {
width: 300px;
height: 300px;
background-color: skyblue;
}
</style>
</head>
<body>
<div class="header">我是顶部导航栏</div>
<div class="sk">秒杀模块</div>
<script>
let sk = document.querySelector('.sk')
let header = document.querySelector('.header')
// 1. 页面滚动事件
window.addEventListener('scroll', function () {
header.style.top = document.documentElement.scrollTop >= sk.offsetTop ? '0' : '-80px'
})
</script>
</body>
十二、阻止元素的默认行为
我们某些情况下需要阻止默认行为的发生,比如阻止链接跳转,表单跳转等
格式
事件对象.preventDefault()
<form action="https://mp.csdn.net/mp_blog/creation/editor/130236424">
<input type="submit" value="跳转网站">
</form>
<script>
const formObject = document.querySelector('form')
formObject.addEventListener('submit', function(e) {
e.preventDefault()
})
</script>