思考
<style>
div {
padding: 20px;
}
.grandparent {
background: orange;
}
.parent {
background:#eee;
}
.child {
background: red;
}
</style>
<div class="grandparent">
grandparent
<div class="parent">parent
<div class="child">child</div>
</div>
</div>
<script>
let grandparent =document.querySelector('.grandparent')
let parent =document.querySelector('.parent')
let child =document.querySelector('.child')
grandparent.addEventListener('click', ()=> {console.log('grandparent')}, false)
parent.addEventListener('click', ()=> {console.log('parent')}, false)
child.addEventListener('click', ()=> {console.log('child')}, false)
</script>
点击child块,依次打印出了
child
parent
grandparent
点击parent块,依次打印出了
parent
grandparent
点击grandparent块,只打印出了
grandparent
addEventListener第三个参数false改为true
<style>
div {
padding: 20px;
}
.grandparent {
background: orange;
}
.parent {
background:#eee;
}
.child {
background: red;
}
</style>
<div class="grandparent">
grandparent
<div class="parent">parent
<div class="child">child</div>
</div>
</div>
<script>
let grandparent =document.querySelector('.grandparent')
let parent =document.querySelector('.parent')
let child =document.querySelector('.child')
grandparent.addEventListener('click', ()=> {console.log('grandparent')}, true)
parent.addEventListener('click', ()=> {console.log('parent')}, true)
child.addEventListener('click', ()=> {console.log('child')}, true)
</script>
点击child块,依次打印出了
grandparent
parent
child点击parent块,依次打印出了
grandparent
parent点击grandparent块,只打印出了
grandparent
W3C规范三个事件阶段
W3C规范中定义了3个事件阶段,依次是捕获阶段
、目标阶段
、冒泡阶段
。事件对象按照上图的传播路径依次完成这些阶段。如果某个阶段不支持或事件对象的传播被终止,那么该阶段就会被跳过。
举个例子,如果Event.bubbles属性
被设置为false
,那么冒泡阶段就会被跳过
。如果Event.stopPropagation()
在事件派发前被调用,那么所有的阶段都会被跳过。
捕获阶段
:
在事件对象到达事件目标之前,事件对象必须从window经过目标的祖先节点传播到事件目标
。
这个阶段被我们称之为捕获阶段。在这个阶段注册的事件监听器在事件到达其目标前必须先处理事件
。
目标阶段
:
事件对象到达其事件目标。 这个阶段被我们称为目标阶段。
一旦事件对象到达事件目标,该阶段的事件监听器就要对它进行处理。如果一个事件对象类型被标志为不能冒泡。那么对应的事件对象在到达此阶段时就会终止传播。
冒泡阶段:
事件对象以一个与捕获阶段相反的方向从事件目标传播经过其祖先节点传播到window。
这个阶段被称之为冒泡阶段。在此阶段注册的事件监听器会对相应的冒泡事件进行处理。
addEventListener()绑定事件,第三个参数默认为false,也就是冒泡,如果为true;则为捕获
任何发生在w3c事件模型中的事件,首是进入捕获阶段,直到达到目标元素,再进入冒泡阶段
我们可以选择是在捕获阶段还是冒泡阶段绑定事件处理函数,这是通过addEventListener()方法实现的,如果这个函数的最后一个参数是true,则在捕获阶段绑定函数,反之false,在冒泡阶段绑定函数。默认为false;
阻止冒泡、取消默认行为)(默认事件)
防止冒泡和捕获
w3c的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true
stopPropagation也是事件对象(Event)的一个方法,作用是阻止目标元素的冒泡事件,但是会不阻止默认行为。什么是冒泡事件?如在一个按钮是绑定一个”click”事件,那么”click”事件会依次在它的父级元素中被触发 。stopPropagation就是阻止目标元素的事件冒泡到父级元素。
终止事件在传播过程的捕获、目标处理或起泡阶段进一步传播。调用该方法后,该节点上处理该事件的处理程序将被调用,事件不再被分派到其他节点。
取消默认事件
w3c的方法是e.preventDefault(),IE则是使用e.returnValue = false;
preventDefault它是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为。既然是说默认行为,当然是元素必须有默认行为才能被取消,如果元素本身就没有默认行为,调用当然就无效了。什么元素有默认行为呢?如a标签(默认行为是跳到指定页面),提交按钮(默认行为是提交表单信息)等。
当Event 对象的 cancelable为false时,表示没有默认行为,这时即使有默认行为,调用preventDefault也是不会起作用的。
return false
原生javascript的return false
只会阻止默认行为jQuery中的return false
既阻止默认行为又防止对象冒泡。
兼容的使用方法(代码)
function test(event) {
//获得event对象兼容性写法
let event = event || (event = window.event);
//获得target兼容型写法
let target = event.target || event.srcElement
//阻止浏览器默认行为兼容性写法
event.preventDefault ? event.preventDefault() : (event.returnValue = false);
//阻止冒泡写法
event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);
}
注意点:
firefox里的event(事件对象)跟IE里的不同,IE里的是全局变量,随时可用;firefox里的要用参数引导才能用,是运行时的临时变量。
在IE/Opera中是window.event,在Firefox中是event;而事件的对象,在IE中是window.event.srcElement,在Firefox中是event.target,Opera中两者都可用。
function a(e){
var e = (e) ? e : ((window.event) ? window.event : null);
// 或者
var e = e || window.event; // firefox下window.event为null, IE下event为null
}
事件对象event
Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。
事件通常与函数结合使用,函数不会在事件发生前被执行!
在一个事件完成了所有阶段的传播路径后,它的Event.currentTarget会被设置为null并且Event.eventPhase会被设为0。Event的所有其他属性都不会改变(包括指向事件目标的Event.target属性).
javascript文档上有关event标准属性的介绍:
属性 | 描述 |
bubbles | 返回布尔值,指示事件是否是起泡事件类型。 |
cancelable | 返回布尔值,指示事件是否可拥可取消的默认动作。 |
currentTarget | 返回其事件监听器触发该事件的元素。 |
eventPhase | 返回事件传播的当前阶段。 |
target | 返回触发此事件的元素(事件的目标节点)。 |
timeStamp | 返回事件生成的日期和时间。 |
type | 返回当前 Event 对象表示的事件的名称。 |
currentTarget
:
currentTarget 事件属性返回其监听器触发事件的节点,即当前处理该事件的元素、文档或窗口。
通俗一点说,就是你的点击事件绑定在哪一个元素上,currentTarget获取到的就是哪一个元素。
target
:
target 事件属性可返回事件的目标节点(触发该事件的节点),如生成事件的元素、文档或窗口。
通俗一点说,就是你当前点击的是哪一个元素,target获取到的就是哪一个元素。
事件对象event.detail
MDN文档-CustomEvent.detail
MDN文档-UIEvent.detail
1,UIEvent.detail是只读属性, 当值为非空的时候, 提供当前连续点击次数(和环境有关) 。 点击一次为1,连续点击两次为2
2,通过代码比如事件对象e.click()触发点击事件时为0
3,对 click 或者 dblclick 事件, UIEvent.detail 是当前点击数量。
4,对 mousedown 或者 mouseup 事件, UIEvent.detail是1加上当前点击数。
5,对所有的其它UIEvent 对象, UIEvent.detail 总是零.
6,接口 CustomEvent 的只读属性 detail (详情)返回在初始化事件对象时传递过来的任何类型数据。
CustomEvent() 用于创建一个自定义事件。
// add an appropriate event listener
obj.addEventListener("cat", function(e) { process(e.detail) });
// create and dispatch the event
let event = new CustomEvent("cat", {
detail: {
hazcheeseburger: true
}
});
obj.dispatchEvent(event);
// Will return an object contaning the hazcheeseburger property
let myDetail = event.detail;
事件对象event的一些兼容性写法
//获得event对象兼容性写法
event || (event = window.event);
//获得target兼容型写法
event.target||event.srcElement
//阻止浏览器默认行为兼容性写法
event.preventDefault ? event.preventDefault() : (event.returnValue = false);
//阻止冒泡写法
event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);