事件
JavaScript事件
一、JavaScript事件简介
- 什么叫事件
当我们点击一个按钮的时候,会弹出一个对话框。在JavaScript中,“点击”这个事情就看做一个事件。“弹出对话框”其实就是我们在点击事件中做的一些事
-
事件该有的3部分
-
事件源:触发谁的事件
-
事件类型:
- 这个事件是干啥的,是点击呢,还是移动呢
-
事件处理函数
var odiv = document.querySelector('div') div.onclick = function(){} //谁来触发事件 → odiv → 这个事件的事件源就是odiv //触发什么事件 → onclick →这个事件类型就是click //触发了之后做什么 → function(){} → 这个事件处理的函数
-
二、事件对象event
-
每触发一个事件都会生成事件对象
-
事件对象包含对事件的描述信息
- 你触发一个点击事件的时候,你点了哪个位置,坐标是多少
- 你触发了一个键盘事件,你按的是哪个按钮
-
获取事假对象
-
在每一个事件处理函数的形参位置,默认第一个就是事件对象
oDiv.onclick = function(e){ console.log(e) }
-
IE兼容性写法:
oDiv.onclick = function (e){ e = e || window.event console.log(e) }
-
三、点击事件的光标点获取
- 每一个点击事件的坐标点都不是一对,因为要有一个相对的坐标系
- 相对事件源(你点击的元素)
- 相对页面
- 相对浏览器窗口
-
相对事件源(你点击的元素)
offsetX
offsetY
-
是相对于你点击的元素的边框内侧开始计算
offsetX
和offset
Y
<style> *{margin:0; padding:0;} div{ width: 300px; height:300px; padding:20px; border;10px solid red; margin:20px 0 0 30px; } </style> <body> <div></div> <script> var oDiv = document.querySelector('div') //绑定点击事件 oDiv.onclick = function(e){ //事件对象兼容写法 e = e || window.event console.log(e.offsetX) console.log(e.offsetY) } </script> </body>
-
-
相对于浏览器窗口
clientX
clientY
-
是相对于浏览器窗口计算,不管你页面滚动到什么情况,都是根据窗口来计算坐标
-
clientX
和clientY
<style> *{margin:0;padding:0;} body{ width:2000px; height:2000px; } div{ width:300px; height:300px; padding:20px; border:10px sosid red; margin:20px 0 0 30px; } </style> <body> <div></div> <script> var oDiv = document.querySelector('div') //绑定点击事件 oDiv.onclick = function(e){ //事件对象兼容写法 e = e || window.event console.log(e.clientX) console.log(e.clientY) } </script> </body>
-
-
-
相对于页面
pageX
pageY
-
是相对于整个页面的坐标点,不管有没有滚动,都是相对于页面拿到的坐标
-
pageX
和pageY
<style> *{margin:0;padding:0;} body{ width:2000px; height:2000px; } div{ width:300px; height:300px; padding:20px; border:10px sosid red; margin:20px 0 0 30px; } </style> <body> <div></div> <script> var oDiv = document.querySelector('div') //绑定点击事件 oDiv.onclick = function(e){ //事件对象兼容写法 e = e || window.event console.log(e.pageX) console.log(e.pageY) } </script> </body>
-
-
四、常见的事件(了解)
-
浏览器事件
load:
页面全部资源加载完毕scroll
浏览器滚动时触发resize
页面大小事件
-
鼠标事件
-
click
点击事件 -
dbclick
双击事件 -
contextmenu
左键单击事件 -
mousedown
鼠标左键按下事件 -
mouseup
鼠标左键抬起事件 -
mousemove
鼠标移动事件 -
mouseover
鼠标移入事件 -
mouseout
鼠标移出事件 -
mouseenter
鼠标移入事件 -
mouseleave
鼠标移出事件-
mouseover
与mouseenter
区别 -
onmouseover
、onmouseout
:鼠标经过时自身触发事件,经过其子元素时也触发该事件;(父亲有的东西,儿子也有) ,支持冒泡onmouseenter
、onmouseleave
:鼠标经过时自身触发事件,经过其子元素时不触发该事件。(父亲的东西就是父亲的,不归儿子所有) ,不支持冒泡
-
-
-
键盘事件
keyup
键盘抬起事件keydown
键盘按下事件keypress
键盘按下抬起事件
-
表单事件
change
表单内容改变事件input
表单内容输入事件submit
表单提交事件
-
触摸事件
touchstart
触摸开始事件touchend
触摸结束事件touchmove
触摸移动事件
-
焦点事件
onblur
失去焦点onfocus
获取焦点
五、事件
鼠标事件
鼠标移入移出改变样式(效果类型于css中的hover)
//鼠标移入
div.onmouseover = function(){
div.style.backguound = 'red'
}
//鼠标移出
div.onmouseover = function(){
div.style.backguound = 'blue'
}
键盘事件
只能给在页面上选中的元素(表单元素)和document来绑定键盘事件
注:不能给页面上的一个div元素设置键盘事件
document.onkeyup = function(){...}
oInput.onkeyup = function(){...}
确定按键
-
我们的键盘上每一个按键都有一个自己独立的编码
-
我们就是靠这个编码来确定我们按下的是哪个按键的
-
我们通过
事件对象 . keyCode
或者事件对象 . which
来获取 -
FireFox2.0不支持
keyCode
,所有要用which
document.addEventListener('keydown', function (e) {
//事件对象的兼容写法
e = e || window.event
//获取键盘码的兼容写法
var keyCode = e.keyCode || e.which
console.log(keyCode)
})
//按下哪个键,控制台输出相应的键码
常见键码(了解)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gbe39Uvs-1628316746982)(C:\Users\song\AppData\Local\Temp\1628253509931.png)]
回车键案例
document.onkeydown = function(e){
//如果是回撤键,执行登录方法
//兼容写法
e = e || window.event
let keyCode = e.keyCode || e.which || e.charCode
//判断是否按下回车键
if(keyCode == 13){
location.href = 'http://www.jd.com'
}
}
组合按键
-
组合按键最主要的就是
alt/shift/ctrl
三个按键 -
在我点击某一个按键的时候判断一下这三个按键有没有按下,有就是组合了,没有就是没有组合
-
事件对象里也为我们提供了三个属性
altKey
:alt键按下得到true,否则得到falseshiftKey
:shift键按下得到true,否则得到falsectrlKey
:ctrl键按下得到true,否则得到false
-
我们就可以通过这三个属性来判断是否都按下了
document.onkeyup = function (e) { e = e || window.event let keyCode = e.keyCode || e.which if (e.altKey && keyCode === 65) { alert('你按下了alt和a') } }
六、事件的绑定方式
事件属性
-
把事假写在标签里面
-
好处:大家都会,几乎所有的浏览器都支持
-
坏处:夹杂在HTML代码中,代码不简介;这种事件写法效率不高;不符合“行为,样式,结构”相分离
<inpute type="button" onclick="alertMessage" value="按钮"
-
事件绑定
-
缺点: 只能给一个元素注册一个事件,绑定一个事件,后一个会覆盖前一个
-
好处: “行为,样式,结构”相分离;便于操作;方便读取事件对象
<div id="div">事件绑定</div> <script> div.onclick = function(){ alert('我是第一个事件') } div.onclick = function(){ alert('我是第二个事件') } </script> //当你点击的时候,只会执行第二个,第一个就没有了,被覆盖掉了
事件监听
addEventListener
非IE7 8下使用
语法: 元素.addEventListener('事件类型',事件处理函数,冒泡还是捕获)
<div id="div">事件绑定</div>
<script>
div.addEventListener('click',function(){
alert('我是第一个事件')
},false)
div.addEventListener('click',function(){
alert('我是第二个事件')
},false)
</script>
//当你点击div的时候,两个函数都会执行,并且会按照你绑定的顺序执行
//先打印 我是第一个事件 ,在打印 我是第二个事件
//注意:事件类型的时候不要写on,点击事件是click,不是onclick
attchEvent
IE7 8 下使用
语法: 元素.attachEvent('事件类型',事件处理函数)
<div id="div">事件绑定</div>
<script>
div.attachEvent('onclick',function(){
alert('我是第一个事件')
})
div.attachEvent('click',function(){
alert('我是第e二个事件')
})
</script>
//当你点击div的时候,两个函数都会执行,并且会按照你绑定的顺序执行
//先打印 我是第二个事件,再 打印我是第一个事件
//注意:事件类型的时候要写on,点击事件就是onclick
两个方式的区别
- 注册事件的时候事件类型参数的书写
addEventListener
不用写onattachEvent
要写on
- 参数个数
addEventListener
一般是三个参数,第三个参数可以不写,默认为false,事件冒泡attachEvent
两个参数
- 执行顺序
addEventListener
顺序注册,顺序执行attachEvent
顺序注册,倒序执行
- 使用浏览器
addEventListener
非IE7 8 浏览器attachEvent
IE7 8 浏览器
七、事件的执行机制
1.事件的传播
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r2mibJDQ-1628316747005)(C:\Users\song\AppData\Local\Temp\1628299520038.png)]
我们点击在红色盒子生上的同时,也是点在了粉色盒子上,那么两个盒子的点击事件都会触发,这个就叫做 事件的传播
- 当元素触发一个事件的时候,其父元素也会触发相同的事件,父元素上的父元素也会触发相同的事件
- 就像上面的图片一样
- 点击在红色盒子上的时候,会触发红色盒子的点击事件
- 也是点击在了粉色盒子上,也会触发粉色盒子的点击事件
- 也是点击在了body上,也会触发body的点击事件
- 也是点击在了HTML上,也会触发HTML的点击事件
- 也是点击在document上,也会触发document上的点击事件
- 也是点在了window上,也会触发window的点击事件
- 也就是说,页面上的任何一个元素触发事件,都会一层一层最终导致window的相同事件触发前提是各层级元素得有注册相同的事件,不然不会触发
在事件传播的过程中,有一些注意的点:
- 只会传播同类事件
- 只会从点击元素开始按照HTML的结构逐层向上元素的事件被触发
- 内部元素不管有没有改事件,主要上层元素有改事件,那么上层元素的事件就会被触发
2.事件传播方向
- 事件确定会从自己开始,到window的所有相同事件都会触发
- 是因为我们点在自己身上,也确定逐层的点在了直至window的每一个元素身上
- 但是到底是先点在自己身上,还是先点在了window身上呢?
- 先点在自己身上,就是先执行自己身上的事件处理函数,逐层向上最后执行window的事件处理函数
- 反之,则是先执行window的事件处理函数,逐层向下,最后执行自己身上的事件处理函数
目标: 你是点击在哪个元素身上,那么这个事件的 目标 就是什么
事件冒泡
- 就是从事件 目标 的事件处理函数,依次向外,直到window的事件处理函数触发,也就是从下向上的执行事件处理函数
- 特点: 事件传播方向,有内向外传
事件捕获
- 就是从 window 的事件处理函数开始,依次向内,直到事件 目标 的事件处理函数执行,也就是从上向下的执行事件处理函数
事件原型图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tPQggiwD-1628316747009)(C:\Users\song\AppData\Local\Temp\1628300952936.png)]
实现:事件捕获和事件冒泡
addEventListener
的第三个参数决定了是事件捕获还是事假冒泡- false:表示注册的事件在冒泡阶段触发-----默认值
- true:表示注册的事件在捕获阶段触发
3.事件目标对象target
target
这个属性是事件对象里面的属性,表示你点击的目标
当你触发点击事件的时候,你点击在哪个元素上,target就是哪个元素
这个target
也不兼容,在IE 下要用srcElement
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
//获取ul元素
var Ul = document.querySelector('ul')
//给ul设置点击事件
Ul.addEventListener('click',function(e){
e = e || window.event
var target = e.target || e.srcElement
console.log(target)
})
</script>
</body>
//当你点击ul的时候,target就是ul
//当你点击在li上面的时候,target就是li
4.事件委托
上面这个代码,当你点击li
的时候,也可以触发ul
的点击事件
并且在事件内部,我们也可以拿到你点击的到底是ul
还是li
这个时候,我们就可以吧li
的事件委托给ul
来做
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
//获取ul元素
var ul = document.querySelector('ul')
//绑定点击事件
ul.addEventListener('click',function(e){
e = e || window.event
var target = e.target || e.srcElement
//判断你点击的是li
if(target.nodeName =='LI'){
//判断你点击的是li
console.log('我是li,我被点击了')
}
})
</script>
</body>
//上面的代码,我们就可以把li要做的事件委托给ul来做
-
为什么要用事件委托
- 我网页上本身没有li
- 我们通过代码添加了一些li
- 添加进来的li是没有点击事件的
- 我每次动态的操作完li之后,要重新给li绑定一次点击事件,比较麻烦
- 这个时候只要委托给ul就可以了
- 因为新加进来的li也是ul的子元素,点击的时候也可以触发ul的点击事件
-
事件委托的书写
- 元素的事件只能委托给结构父级或者再结构父级的同样事件上
- li的点击事件,就不能委托给ul的鼠标移入事件
- li的点击事件,只能委托给ul或者在更高父级的点击事件上
5.阻止事件传播
e.stopPropagstion()
标准浏览器
e.cancelBubble=true
IE低版本
兼容写法
if(e.stopPropagation){
e.stopPropagation()
}else{
e.cancelBubble=true
}
6.默认行为
阻止默认行为
有时候,我们不希望浏览器执行默认事件
比如我给a
标签设置了一个点击事件,我点击的时候希望你告诉我你的地址是什么
而不是直接跳转链接
那么,我们就要把a
标签原先的默认事件阻止,不让他执行默认事件
两个方法来阻止默认事件
e.preventDefault()
: 非 IE 使用
e.returnValue = false :
IE 使用
<a href = "https://www.jd.com" >我是一个链接</a>
<script>
var a = document.querySelector('a')
a.addEventListener('click',function(e){
e = e || window.event
console.log(this.href)
e.preventDefault ? e.preventDefault() : e.returnValue = false
})
</script>
- 这样写完以后,你点击a标签的时候,就不会跳转链接了
- 而是会在控制台打印a标签的href属性的值