事件下:
事件执行机制
<style>
div.big{ width: 400px; height: 400px;background-color: pink;position:relative;}
div.small{width: 200px;height: 200px;background-color: red;position: absolute;top:100px;left:100px;}
</style>
<body>
<div class="big">
<div class="small"></div>
</div>
<script>
var big = document.querySelector('.big');
var small = document.querySelector('.small');
big.onclick = function(){
console.log('big的click发生了')
}
small.onclick = function(){
console.log('small的click发生了')
}
document.body.onclick = function(){
console.log('body的click发生了')
}
</script>
-
1.事件执行机制?
- 当元素触发一个事件的时候,其父元素也会触发相同的事件,父元素的父元素也会触发相同的事件.
- 事件传播:
- 像大盒子套小盒子一样,我们点击小盒子身上的时候,也是点击在了大盒子上,这是既定事实,那个两个盒子的点击事件都会触发。
-
在事件传播的过程中,要注意:
- 1.只会传播同类事件.
- 2.只会从点击元素开始,按照html的结构逐层向上元素的事件都会触发.
- 3.内部元素不管有没有该事件,只要上层元素有该事件,那么上层元素的事件就会被触发.
-
先点在自己身上,就是先执行自己身上的事件,再逐层向上最后执行window上的事件处理函数.反之,那么先执行window的事件处理函数,逐层向下最后执行自己身上的事件处理函数.
-
2.冒泡、捕获、目标:
事件会从自己身上逐层向上传播.
目标:- 点击那个元素就是目标
冒泡: - 从事件目标的事件处理函数开始,依次向外,直到window的事件处理函数触发.(从上到下的执行事件处理函数)
捕获: - 从window的事件处理函数开始,依次向内执行,直到事件目标就是事件处理函数触发.(从上向下的执行事件函数.)
- 点击那个元素就是目标
-
冒泡和捕获的区别:
就是在事件的传播中,多个同类事件处理函数的执行顺序不同、IE浏览器不支持捕获事件、事件先捕获,再冒泡
<script>
var big = document.querySelector('.big');
var small = document.querySelector('.small');
//通过事件监听注册事件
small.addEventListener('click',function(){
console.log('small click')
},true)
big.addEventListener('click',function(){
console.log('big click')
},true)
document.body.addEventListener('click',function(){
console.log('body click')
},true)
</script>
- 3.事件委托:
-
把要做的事情委托给别人。利用冒泡机制,点击子元素的时候 ,也会触发父元素点击事件,所以我们就可以把子元素的事件委托给父元素.
-
事件委托的书写:
- 1.元素的事件只能委托给父元素或者父元素的父元素的同样的事件上.
- 2.li的点击事件,就不能委托给ul的鼠标移动事件.
- 3.li元素的点击事件,只能委托给ul或再高父元素的点击事件.
-
- 3.1事件委托案例:
- 当我们点击 li 的时候,也可以触发 ul 的点事件.
- 并且在事件内不,我们也可以拿到你点击的到底是 ul 还是 li.
- 这个时候,我们就可以把 li 的事件委托给 ul 来做.
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var oUl = docuemnt.querySelector('ul')
oUl.addEventListener('click', function (e) {
e = e || window.event
var target = e.target || e.srcElement
// 判断你点击的是 li
if (target.nodeName.toUpperCase === 'LI') {
// 确定点击的是 li
// 因为当你点击在 ul 上面的时候,nodeName 应该是 'UL'
// 去做点击 li 的时候该做的事情了
console.log('我是 li,我被点击了')
}
})
</script>
</body>
为什么要用事件委托
-
因为:
- 页面上本身没有 li
- 通过代码添加了一些 li
- 添加进来的 li 是没有点击事件的
- 每次动态的操作完 li 以后都要从新给 li 绑定一次点击事件
- 比较麻烦
- 这个时候只要委托给 ul 就可以了
- 因为新加进来的 li 也是 ul 的子元素,点击的时候也可以触发 ul 的点击事件
-
3.2事件触发:
- 点击子元素的时候,不管子元素有没有点击事件,只要父元素有点击事件,那么就可以触发父元素的点击事件. -
事件触发案例:
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var oUl = docuemnt.querySelector('ul')
oUl.addEventListener('click', function (e) {
console.log('我是 ul 的点击事件,我被触发了')
})
</script>
</body>
-
像上面一段代码,当你点击 ul 的时候肯定会触发.
-
但是当你点击 li 的时候,其实也会触发.
-
4.事件冒泡:
- 就是事件从目标开始,依次向外,直到window的事件处理函数触发.
<body>
<div class="big">
<div class="small"></div>
</div>
- 目标是small-->big-->body-->html-->document-->window.
- 阻止冒泡:
- 如果在事件传播过程中,中断传播,就不会继续传播到window了,这个叫做阻止冒泡.
- 如果在big中断,那么,点击small=>small的点击事件会发生,big的点击事件也会发生,但是在big中断传播,那么从big后面的上级元素事件就不会触发了.
- 事件对象上有一个方法,可以阻止事件的传播,这个方法使e.stopPropagation.
=>这个方法有兼容性问题,e.cancelBubbble = true;
阻止冒泡的兼容写法:(三目)
e.stopPropagation?e.stopPropagation():e.cancelBubble=true;
- 案例:
var small = document.querySelector('.small')
var big = document.querySelector('.big')
small.onclick = function(e){
console.log('small click');
}
big.onclick = function(e){
e = window.event||e;
//如果在big中断,那么,点击small
//small的点击事件会发生,big的点击事件也会发生,但是在big中断传播,那么从big后面的上级元素事件就不会触发了
//阻止冒泡的兼容写法:
e.stopPropagation?e.stopPropagation():e.cancelBubble=true;
console.log('big click')
}
document.body.onclick = function(){
console.log('body click')
}
document.documentElement.onclick = function(){
console.log('html click')
}
document.onclick = function(){
console.log('document click')
}
window.onclick = function(){
console.log('window click')
}
- 5.默认行为:
- 不用我们注册事件,他自己就存在的事件.
- 比如:我们点击a标签的时候,我们不需要注册点击事件,他自己就会跳转页面.
- 不用我们注册事件,他自己就存在的事件.
- 阻止默认行为:
- 比如,给a标签绑定了一个点击事件,我点击的时候希望你干什么你就干什么,而不是直接跳转.
两个方法来阻止默认事件:- e.preventDefault(); 非IE使用
- e.returnValue = false; IE使用
- 比如,给a标签绑定了一个点击事件,我点击的时候希望你干什么你就干什么,而不是直接跳转.
- 兼容写法: e.preventDefault?e.preventDefault:e.returnValue = false ;
- 案例:
<a href="http://www.baidu.com">baidu</a>
<script>
var a = document.querySelector('a');
a.onclick = function(e){
e = window.event||e;
//不要执行默认的跳转动作
e.preventDefault?e.preventDefault():e.returnValue=false;
console.log(1)
}
</script>
- 6.补充:
- 6.1.target:这个属性是事件对象里面的属性,表示你点击的目标.(不兼容ie)
- 当你触发点击事件的时候,你点击在哪个元素上,target 就是哪个元素.
** target 不兼容IE,在 IE 下要使用 srcElement**
兼容写法:
- 当你触发点击事件的时候,你点击在哪个元素上,target 就是哪个元素.
- var target = e.target || e.srcElement;
- 6.1.target:这个属性是事件对象里面的属性,表示你点击的目标.(不兼容ie)
- 案例:
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var oUl = docuemnt.querySelector('ul')
oUl.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.