1.关于js中事件的等级划分:
(1).DOM0事件:eg:onclick等事件,直接使用dom.onclick=function(){}等,即将事件监听挂在节点上,回调中的this直接指向当前节点;此类事件缺点是之只能为为节点绑定一次相同的事件:
eg:<body>
<div>
<span id="eve">添加事件</span>
</div>
<script>
let eve = document.getElementById('eve')
eve.onclick=()=>{
console.log('点1')
}
eve.onclick=()=>{
console.log('点2')
}
</script>
</body>
运行结果只会出现点2,即第二次定义的onclick会覆盖第一次定义的onclick
(2).DOM1:未涉及事件相关
(3).DOM2事件:eg:addEventListener('click',function(){},false)这类事件
其中最后的参数false代表冒泡阶段,如果参数为true则代表捕获阶段;
该事件绑定的有点是不会发生像DOM0事件一样的事件覆盖,eg:
<body>
<div>
<span id="eve">添加事件</span>
</div>
<script>
let eve = document.getElementById('eve')
eve.addEventListener('click',(e)=>{
console.log('1')
})
eve.addEventListener('click',(e)=>{
console.log('2')
})
</script>
</body>
本段代码会输出1,2
(4).DOM3事件:eg:addEventListener('keyup',function(){},false)这类事件
从本质上说是和DOM2操作差不多的,但是新增了鼠标和键盘等更多类事件
2.关于事件的冒泡和捕获
(1)事件模型:捕获和冒泡
(2)冒泡的一个具体应用场景:想象一下现在我们有一个10列、100行的HTML表格,你希望在用户点击表格中的某一单元格的时候做点什么。比如说我有一次就需要让表格中的每一个单元格在被点击的时候变成可编辑状态。如果把事件处理器加到这1000个单元格会产生一个很大的性能问题,并且有可能导致内存泄露甚至是浏览器的崩溃。相反地,使用事件代理的话,你只需要把一个事件处理器添加到table元素上就可以了,这个函数可以把点击事件给截下来,并且判断出是哪个单元格被点击了
(2)事件流:捕获->目标阶段->冒泡
(3)DOM事件捕获的具体流程:window->document->html->body->对应dom层次->目标
冒泡的具体流程与此相反。
各节点层次在js中如何获取:
window:window
document:document
html:docunment.documentElement
body:document.body
dom:document.getElementsID()等
现在用js代码来具体描述捕获的具体流程:
<body>
<div>
<span id="eve">添加事件</span>
</div>
<script>
let eve = document.getElementById('eve')
window.addEventListener('click',()=>{
console.log('我是window,已经捕获')
},true)
document.addEventListener('click',()=>{
console.log('我是document,已经捕获')
},true)
document.documentElement.addEventListener('click',()=>{
console.log('我是html,已经捕获')
},true)
document.body.addEventListener('click',()=>{
console.log('我是body,已经捕获')
},true)
eve.addEventListener('click',()=>{
console.log('我是点击目标,已经捕获')
},true)
window.addEventListener('click',()=>{
console.log('我是window,已经冒泡')
},false)
document.addEventListener('click',()=>{
console.log('我是document,已经冒泡')
},false)
document.documentElement.addEventListener('click',()=>{
console.log('我是html,已经冒泡')
},false)
document.body.addEventListener('click',()=>{
console.log('我是body,已经冒泡')
},false)
eve.addEventListener('click',()=>{
console.log('我是点击目标,已经冒泡')
},false)
</script>
</body>
</html>
运行结果如下:
我是window,已经捕获
我是document,已经捕获
我是html,已经捕获
我是body,已经捕获
我是点击目标,已经捕获
我是点击目标,已经冒泡
我是body,已经冒泡
我是html,已经冒泡
我是document,已经冒泡
我是window,已经冒泡
3.关于自定义事件:
关于自定义事件可以有两种定义方法
第一种就是Event
如果后面要跟参数则可以使用第二种CustomEvent
步骤:
1.let event = new Event('defineEvent')或者let event = new CustomEvent('defineEvent')//定义事件名
2.dom.addEventListener('defineEvent',()=>{},false)//添加事件监听器
3.dom.dispatchEvent(event)//执行事件
下面就用js来实现:
<body>
<div>
<span id="eve">添加事件</span>
</div>
<script>
let eve = document.getElementById('eve')
let event = new CustomEvent('defineEvent',{detail:{a:'我是参数'}})//定义事件名
eve.addEventListener('defineEvent',(e)=>{
console.log(e.detail.a)
},false)//添加事件监听器
eve.dispatchEvent(event)//执行事件
</script>
</body>
4.关于事件event常用api
event.preventDefault()//阻止默认事件发生,比如点击链接后浏览器会自动跳转等
event.stopPropagation()//阻止事件冒泡到父元素
event.currentTarget//事件所绑定的元素
event.target//指的是引起事件出发的元素
event.stopImmediatePropagetion()//阻止后续绑定在相同元素上的事件触发
eg:
<body>
<div id='hhh'>
<span id="eve">添加事件</span>
</div>
<script>
let eve = document.getElementById('eve')
let hhh = document.getElementById('hhh')
eve.addEventListener('click',(e)=>{
console.log('我是点击目标,已经冒泡',e.currentTarget.id+':'+e.target.id+e.clientX)
e.stopImmediatePropagation()
},false)
eve.addEventListener('click',(e)=>{
console.log('我是点击目标,已经冒泡kkkkkk',e.currentTarget.id+':'+e.target.id+e.clientX)
},false)
eve.addEventListener('mouseleave',(e)=>{
console.log('我是点击目标,已经冒泡kkkkkk',e.currentTarget.id+':'+e.target.id+e.clientX)
},false)
只会输出第一个事件的输出值
</script>
event.clientX//鼠标点击点以浏览器左定点为座标原点的横座标
event.keyCode//键盘操作的键盘码字