Javascript 事件监听
1.addEventListener()
- 语法:node.addEventListener(事件名称,回调函数,是否使用事件捕获传递)
- 第三个参数:可以是布尔值,就用来描述是否使用事件捕获传递,默认为false,即冒泡传递,如果设为true,则代表为捕获传递,也可以是一个配置对象
<script>
var ul = document.querySelector('ul')
//冒泡传递
ul.addEventListener('click',function(){
console.log('点击了ul 冒泡传递')
})
//捕获传递
ul.addEventListener('click',function(){
console.log('点击了ul 捕获传递 - 1')
},true)
//捕获传递
ul.addEventListener('click',function(){
console.log('点击了ul 捕获传递 - 2')
},{capture: true})
//只执行一次
var button = document.querySelector('button')
button.addEventListener('click',function(){
console.log('点击了button')
},{once: true})
</script>
- 此方式可以给同一个Dom元素的同一事件绑定多个回调(但是不能是同一个事件回调,多余的添加将自动被去除)
var ul = document.querySelector('ul')
ul.addEventListener('click',function(){
console.log('点击了ul')
})
ul.addEventListener('click',function(){
console.log('点击了ul - 2')
})
- 兼容性:Internet Explorer 8 及更早IE版本不支持 addEventListener() 方法,,Opera 7.0 及 Opera 更早版本也不支持,解决办法
function addEvent(obj,type,func){
if (obj.addEventListener) {
obj.addEventListener(type, func,false);
} else {
obj.attachEvent("on"+type, func);
}
}
function removeEvent(obj,type,func){
if (obj.removeEventListener) {
obj.removeEventListener(type, func,false);
} else {
obj.detachEvent("on"+type, func);
}
}
2.on + 事件名称
- 直接在标签中通过 on + 事件名称 添加事件监听
<p onclick="someFn()">11111</p>
- 通过Dom元素赋值属性的形式添加
document.querySelector('p').onclick=someFn
- 上面2种方法操作的是同一个东西,都是对Dom的属性进行定义,所以相互直接会覆盖(最终生效的只有test3)
var ul = document.querySelector('ul')
ul.onclick = test2
ul.onclick = test3
function test(){
console.log('test')
}
function test2(){
console.log('test2')
}
function test3(){
console.log('test3')
}
- on + 事件名称使用的是冒泡传递
<body>
<ul onclick="test('ul')">
<li onclick="test('li')">
<p onclick="test('p')">1111</p>
</li>
</ul>
</body>
</html>
<script>
function test(msg){
console.log(msg)
}
</script>
点击这个区域,依次打印(事件由内到外传递)
p
li
ul
3.查看元素所绑定的事件
- F12->选择Dom元素->事件监听器(元素所有绑定的事件都在此显示,包括自定义事件)
4.移除事件监听
- 还可以直接通过UI界面进行移除
- Js方式移除:removeEventListener(事件名称,回调名称)
- 注意:只能移除addEventListener()方法添加的事件,且事件回调,传递机制要一样(也就是说回调方法不能是匿名)
// 向 <div> 元素添加事件句柄
document.getElementById("myDIV").addEventListener("click", myFunction);
// 移除 <div> 元素的事件句柄
document.getElementById("myDIV").removeEventListener("click", myFunction);
5.冒泡与捕获
- 事件基本流程:多个元素相互嵌套,事件一旦触发,最外层的元素最先感知,然后依次传递给自己的子元素,而一直传递到最内层的元素后,会反方向依次传递给父元素
- 冒泡与捕获:由外到内的这个过程叫做捕获,由内到外这个过程叫做冒泡
- 触发时机:只能在捕获和冒泡两个过程中选一个时机执行回调,使用冒泡机制就是在冒泡的过程中才执行,使用捕获机制就是在捕获过程中执行,不理解可以看图
- 通俗的说,冒泡就是先执行内层元素事件,再外层元素事件,而捕获则相反,先执行外层元素事件,再执行内层元素事件
- 以上的内容由个人测试总结而来,不保证专业(测试代码已删)
6.事件触发
- 事件名称 + ():原生事件可以通过该方式进行触发(click,focus,blur),不同方式添加的事件监听都能执行(onclick/addEventListener),还支持冒泡,默认事件需要有相关的用户动作才能执行
<body>
<div id="box">
<ul>
<li>列表</li>
</ul>
</div>
<a href="https://www.baidu.com" target="_blank">百度一下</a>
<button>点我</button>
</body>
<script>
//外层元素
var ul = document.querySelector("ul")
//外层事件监听
ul.onclick = function(){
console.log("onclick ul")
}
ul.addEventListener("click",function(){
console.log("addEventListener ul")
})
//触发外层元素点击事件(原生事件)
ul.click()
//输出onclick ul
//输出addEventListener ul
console.log('---')
//内层元素
var li = document.querySelector("li")
//内层事件监听
li.addEventListener("click",function(){
console.log("addEventListener li")
})
//触发内层元素点击事件(原生事件),说明支持冒泡
li.click()
//输出addEventListener li
//输出onclick ul
//输出addEventListener ul
//默认事件测试
var link = document.querySelector("a")
//模拟点击
setTimeout(() => {
//模拟点击
link.click() //弹窗被阻止,默认事件不支持
}, 1000)
//点击其他位置来模拟改链接点击链接
document.querySelector('button').onclick = function(){
//点击button按钮,进入此事件回调,因为有点击动作,虽然点的不是当前链接标签,但是此次默认事件可以执行
link.click()
}
</script>
- 通过创建事件对象来模拟触发,可以设定此次触发时是否冒泡机,是否可以阻止默认事件等等
<body>
<div class="box">
<ul>
<li>li</li>
</ul>
</div>
<button onclick="triggerClick(false)">bubbles:false</button>
<button onclick="triggerClick(true)">bubbles:true</button>
</body>
<script>
var box = document.querySelector('.box')
var ul = document.querySelector('ul')
var li = document.querySelector('li')
//box事件监听
box.addEventListener('click',function(e){
console.log('click box - 冒泡')
},false)
box.addEventListener('click',function(e){
console.log('click box - 捕获')
},true)
//ul事件监听
ul.addEventListener('click',function(e){
console.log('click ul - 冒泡')
},false)
ul.addEventListener('click',function(e){
console.log('click ul - 捕获')
},true)
//li事件监听
li.addEventListener('click',function(e){
console.log('click li - 冒泡')
},false)
li.addEventListener('click',function(e){
console.log('click li - 捕获')
},true)
//按钮监听回调
function triggerClick(bubbles = false){
console.log('bubbles = ',bubbles)
//创建事件对象
var ev = new Event(
'click',
{
'bubbles': bubbles,//表示是否冒泡,默认false,false表示不会触发其外层元素在冒泡阶段的回调事件,则true则表示会
'cancelable': false,//经测试效果未知
}
)
//模拟触发
ul.dispatchEvent(ev)
}
</script>
- 自定义事件的定义和触发
<script>
var box = document.querySelector(".box")
//自定义事件,移除当前元素的子元素
box.addEventListener('removeChild',function(event,index){
//第一个参数为event
console.log(event) //CustomEvent{}
var children = this.children
this.removeChild(children[1])
})
var event = new CustomEvent('removeChild', { bubbles:true,cancelable:true }) //使用冒泡机制 允许用户禁止
box.dispatchEvent(event,1)
</script>