事件处理模型——事件冒泡、捕获
- 事件冒泡(不绑定事件处理函数一样会发生冒泡事件)
- 结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一个事件,自子元素冒泡向父元素(自底向上)
-
<div class="first" style="width: 300px; height: 300px; background-color: red;"> <div class="secend" style="width: 200px; height: 200px; background-color: yellow;"> <div class="end" style="width: 100px; height: 100px; background-color: green;"></div> </div> </div> <script> var first = document.getElementsByClassName("first")[0]; var secend = document.getElementsByClassName("secend")[0]; var end = document.getElementsByClassName("end")[0]; first.onclick=function(){ console.log("123"); }; secend.onclick=function(){ console.log("456"); }; end.onclick=function(){ console.log("789"); } </script> 我们同时在三个div上绑定了事件,现在三个div存在嵌套的关系,当我们点击最里层的div的时候,就会触发相关的事件冒泡,外边的两个父类div的事件都会被触发,这就是事件冒泡(先触发自己的事件,然后依次向父级)
-
- 结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一个事件,自子元素冒泡向父元素(自底向上)
2.事件捕获
- 结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一个事件,自复父元素捕获至子元素(事件源元素)(自顶向下)
-
<div class="first" style="width: 300px; height: 300px; background-color: red;"> <div class="secend" style="width: 200px; height: 200px; background-color: yellow;"> <div class="end" style="width: 100px; height: 100px; background-color: green;"></div> </div> </div> <script> var first = document.getElementsByClassName("first")[0]; var secend = document.getElementsByClassName("secend")[0]; var end = document.getElementsByClassName("end")[0]; first.addEventListener('click',function(){ console.log("123"); },true); //当这个true为false时就不会触发事件捕获,但是会触发事件冒泡 secend.addEventListener('click',function(){ console.log("456"); },true); end.addEventListener('click',function(){ console.log("789"); },true) </script>
我们同时也在三个div上绑定了事件,它们存在嵌套关系,现在我们点击最里边的事件,就会触发捕获事件(先触发被点击的事件的最外层的父级元素的事件,依次向里),这就是事件捕获
- 触发顺序:先捕获,后冒泡
- focus blur change submit reset select 等事件不冒泡
- 取消冒泡
- W3C标准event.stopPropagation(); 但不支持ie9以下版本
-
end.onclick=function(e){ e.stopPropagation(); //这就会组织冒泡事件的发生 e代表这个是事件的本身 console.log("789"); }
- IE独有event.cancelBubble=true;(这个上边的功能是一样的,写法也是一样的)
- 阻止默认事件
- 首先我们先说说什么是默认事件
- 默认事件——表单提交 a标签跳转 右键菜单
- 我们如何来阻止这些默认事件呢? return false ;以对象属性的方式注册的事件才生效
-
document.oncontextmenu=function(){ //阻止鼠标右键菜单的默认事件 console.log("123"); return false; }
- event.preventDefault(); W3C标准,IE9以下不兼容
-
document.oncontextmenu=function(e){ console.log("123"); e.preventDefault(); }
-
- event.returnValue=false; 兼容IE
-
document.oncontextmenu=function(e){ console.log("123"); e.returnValue=false; }
-
- 首先我们先说说什么是默认事件
- 事件对象
- event || window.event 用于IE
事件源对象:(虽然我们前边说过事件存在冒泡,但是我们可以通过下边的方法找到我们所触发的事件源对象) - event.target 火狐只有这个
- event.srcElement IE只有这个
- 这俩Chrome都有
- 我们来使用事件源实现一个很使用的编程题
-
<!-- 现在我们有这样的需求,我们需要在ul下的li中给每一个里都绑定事件,当点击某一个li时,展示li中的内容 --> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> <li>9</li> <li>10</li> </ul> <script> var ul = document.getElementsByTagName("ul")[0]; ul.onclick = function(e){ var event = e || window.event; if(event.target){ console.log(event.target.innerText); //获取事件源元素的文本内容 }else{ console.log(event.srcElement.innerText); } } //这个例子就没有用到for循环,大大减少了运行的事件,把事件绑定在父元素上,点击子元素时,父元素去找事件源,再处理先关的事件源
</script> - 学到这里,相信大家对事件都有差不多的了解了,那我们现在来实现一个鼠标拖动事件:
-
<div style="width: 50px; height: 50px; background-color: red; position: absolute; left: 0px; top: 0px; "></div> <!-- 现在我想实现鼠标的拖动事件 --> <script> var div = document.getElementsByTagName("div")[0]; div.onmousedown = function(ev){ //鼠标按下执行的函数 //event的兼容性 var ev = ev||window.event; //获取鼠标按下的坐标 var x1 = ev.clientX; var y1 = ev.clientY; //获取元素的left,top值 var l = div.offsetLeft; //直接返回的数字,没有px var t = div.offsetTop; //给可视区域添加鼠标的移动事件 document.onmousemove = function(ev){ //鼠标移动执行的函数 //event的兼容性 var ev = ev||window.event; //获取鼠标移动时的坐标 var x2 = ev.clientX; var y2 = ev.clientY; //计算出鼠标的移动距离 var x = x2-x1; var y = y2-y1; //移动的数值与元素的left,top相加,得出元素的移动的距离 var lt = y+t; var ls = x+l; //更改元素的left,top值 div.style.top = lt+'px'; div.style.left = ls+'px'; } //清除 document.onmouseup = function(ev){ //鼠标按键抬起执行的函数 document.onmousemove = null; } } </script>
-
做最好的自己,不努力永远看不到自己的光环。别在该努力的年纪享乐,就不会在该享乐的年纪吃苦!