事件的原理--自定义事件--抛发事件
//事件抛发 //首先给div0 添加一个我们没见过的事件 也就是e.type div0.addEventListener("chilema",fn1); //实例化事件对象,并且创建一个chilema的事件 var evt=new Event("chilema"); //div0 自己抛发这个事件,并执行fn1 div0.dispatchEvent(evt); function fn1(){ console.log("我吃了"); }
事件默认是由冒泡触发的,通过Elelement.addEventHandeterLister("click",clickHandler,ture); 第三个参数来修改,默认是flase 捕获不触发
事件触发由三个阶段组成
1.捕获阶段, 在经过捕获阶段时,是由最外层 document 往内部进行捕获 (事件也可以由捕获触发)
2.目标阶段 到达目标
3.冒泡阶段 到达目标后在由内向外冒泡触发事件(默认)
<script> //获取div0 div1 div2 DOM var div0=document.querySelector(".div0"); var div1=document.querySelector(".div1"); var div2=document.querySelector(".div2"); //添加事件监听 其中e 是鼠标事件 e.target 是目标对象 e.currentTarget和this一样都是侦听对象 div0.addEventListener("click",clickHandler0); function clickHandler0(e){ console.log(e.target,e.currentTarget,this); } div1.addEventListener("click",clickHandler1); function clickHandler1(e){ console.log(e.target,e.currentTarget,this); } div2.addEventListener("click",clickHandler2); function clickHandler2(e){ console.log(e.target,e.currentTarget,this); } </script>
上述代码,当我们点击最里面的div2的时候,e.currentTarget的 div2、div1、div0 事件是由内向外触发的--也就是冒泡触发
我们来修改代码,把事件监听的第三个参数改成true
<script> //获取div0 div1 div2 DOM var div0=document.querySelector(".div0"); var div1=document.querySelector(".div1"); var div2=document.querySelector(".div2"); //添加监听事件,在捕获阶段触发 div0.addEventListener("click",clickHandler0,true); function clickHandler0(e){ console.log(e.target,e.currentTarget,this); } div1.addEventListener("click",clickHandler1,true); function clickHandler1(e){ console.log(e.target,e.currentTarget,this); } div2.addEventListener("click",clickHandler2,true); function clickHandler2(e){ console.log(e.target,e.currentTarget,this); } </script>
以上代码e.currentTarget就显示的 div0、div1、div2 也就是说在捕获阶段触发的事件
案例1: 当我们点击div2的时候让每个元素,没过1秒后 背景颜色依次变成透明的
<script> var div0=document.querySelector(".div0"); var div1=document.querySelector(".div1"); var div2=document.querySelector(".div2"); var num=1; div0.addEventListener("click",clickHandler0); function clickHandler0(e){ //setTimeOut 有三个参数,第一个是参数:回调函数,第二个参数是多少秒后执行,第三个参数可以传递一个参数进去, //之后可以在第一个参数 回调函数中接受 重要 setTimeout(function (div){ //这养设置透明 整体都会透明 // div.style.opacity="0.2"; //当我们点击事件的时候,我们一次让这些元素 没过一秒 背景颜色变成透明的 div.style.backgroundColor="rgba(255,0,0,0.2)"; },num*1000,this); num++; } div1.addEventListener("click",clickHandler1); function clickHandler1(e){ setTimeout(function (div){ div.style.backgroundColor="rgba(0,255,0,0.2)"; },num*1000,this); num++; } div2.addEventListener("click",clickHandler2); function clickHandler2(e){ setTimeout(function (div){ div.style.backgroundColor="rgba(0,0,255,0.2)"; },num*1000,this); num++; } </script>
案例二:综合上面案例,我们可不可以,先让div0变透明,在是div2 ,再是div1呢---那只要把div0 设置捕获阶段触发就好了
<script> var div0=document.querySelector(".div0"); var div1=document.querySelector(".div1"); var div2=document.querySelector(".div2"); var num=1; div0.addEventListener("click",clickHandler0,true); function clickHandler0(e){ //setTimeOut 有三个参数,第一个是参数:回调函数,第二个参数是多少秒后执行,第三个参数可以传递一个参数进去, //之后可以在第一个参数 回调函数中接受 重要 setTimeout(function (div){ //这养设置透明 整体都会透明 // div.style.opacity="0.2"; //当我们点击事件的时候,我们一次让这些元素 没过一秒 背景颜色变成透明的 div.style.backgroundColor="rgba(255,0,0,0.2)"; },num*1000,this); num++; } div1.addEventListener("click",clickHandler1); function clickHandler1(e){ setTimeout(function (div){ div.style.backgroundColor="rgba(0,255,0,0.2)"; },num*1000,this); num++; } div2.addEventListener("click",clickHandler2); function clickHandler2(e){ setTimeout(function (div){ div.style.backgroundColor="rgba(0,0,255,0.2)"; },num*1000,this); num++; } </script>
onclick事件 它不可以一个事件多个方法,addEventListener可以针对一个对象一个事件多个方法,并且可以使用removeAddEventListener中间
停止某些方法。
onclick事件不能设置捕获和冒泡阶段那个有限addEventListener及是否选定一个被另一个覆盖
onlcikc事件没有自由度,addEventListener可以侦听任何自定义事件--比如chilema onchilema没有
e.Propagation(); 阻止冒泡
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> #div0{ 100px; height:100px; background-color: red; margin: auto; display: flex; } #div1{ 50px; height:50px; background-color: chartreuse; margin: auto; } </style> </head> <body> <div id="div0"> <div id="div1"></div> </div> <script> var div0=document.querySelector("#div0"); var div1=document.querySelector("#div1"); div0.addEventListener("click",clickHandler0); div1.addEventListener("click",clickHandler1); function clickHandler0(e){ console.log('aaaa'); } function clickHandler1(e){ e.stopPropagation(); //阻止冒泡 ,这个我们点击div1的时候 div0的事件就不会被触发了 console.log('bbb'); } </script> </body> </html>
案例:通过给UL添加事件,实现点击li元素添加样式
<ul> <li>吉林</li> <li>上海</li> <li>北京</li> </ul> <script> //如果给li添加事件,li的条目要是多的话 就会占用多的内存 //这里给ul添加事件 var bool=false; var ul=document.getElementsByTagName('ul')[0]; ul.addEventListener("click",clickHandler); function clickHandler(e){ //e.target 是我们点击的目标对象 e.target.style.backgroundColor="red"; } </script>
案例:
<!-- <ul> <li>吉林 <ul> <li>通辽</li> <li>南关</li> <li>长春 <ul> <li>净月</li> <li>高新</li> <li>经开</li> </ul> </li> <li>四平</li> <li>沈阳</li> </ul> </li> <li>上海 <ul> <li>嘉定</li> <li>马路</li> <li>虹桥</li> <li>安亭</li> </ul> </li> <li>北京 <ul> <li>城西</li> <li>人民</li> <li>城南</li> </ul> </li> </ul> <script> var li=document.getElementsByTagName("li"); for(var i=0;i<li.length;i++){ li[i].addEventListener('click',clickHandler); } function clickHandler(e){ e.stopPropagation(); this.bool=!this.bool; if(this.firstElementChild.style=="null"){ console.log("aaa"); } if(this.bool){ this.firstElementChild.style.display="none"; return; } this.firstElementChild.style.display="block"; } </script> -->