面试准备:js事件绑定,事件委托,dom流事件总结

  1. Js中的事件:

   Onsubmit:用于表单提交之前,验证所有表单。

   Onload和onunload用户进入或离开时触发,可用于处理cookie

   Onload主要用于Body标签:页面一加载就触发

   Onmouseenter ,onmouseover,onmouseleave等为鼠标事件

   表单事件:表单元素事件,在表单元素中才有效

     onchange     框内容改变时

     onsubmit     点击提交按钮时

     onreset     重新点击鼠标按键时

     onselect     文本被选择时

     onblur      元素失去焦点时

     onfocus     当元素获取焦点时

扫描二维码关注公众号,回复: 11049170 查看本文章

    键盘事件:onkeydown, onkeyup, onkeypress

    鼠标事件:

    onclick      鼠标点击一个对象时

    ondblclick    鼠标双击一个对象时

    onmousedown 鼠标被按下时

    onmousemove 鼠标被移动时

    onmouseout    鼠标离开元素时

    onmouseover 鼠标经过元素时

    onmouseup    释放鼠标按键时

   2.Js中的事件绑定机制:

   ①行内支持以on开头的onclick,onblur等以on开头的【不能实现事件重复绑定】

<button onclick="var i=1;alert(i)">弹出</button>

   ②当代码较多时,在onclick中指定函数名。【不能实现事件重复绑定】

    <div id="box" onclick="func()"></div>

  ③在js代码中通过dom元素onclick等属性【不能实现事件重复绑定】

 var b=document.getElementById('box');
     b.onclick=function(){
       b.style.backgroundColor ='blue';
  }

④使用W3C标准的addEventListener和removeEventListener。

type:事件类型,不含"on",比如"click"、"mouseover"、"keydown";

// listener:事件处理函数

// useCapture是事件冒泡,默认false:事件冒泡(由向校外),反之true

addEventListener(type, listener, useCapture);

  var btn=document.getElementsByTagName('button')[0];
      btn.addEventListener('click',function(){
        alert(2)
   })

   a) 事件处理函数中this代表的是dom对象,不是window,这个特性与attachEvent不同。

   b) 同一个事件处理函数可以绑定2次,一次用于事件捕获,一次用于事件冒泡。

   但如果绑定同一个事件处理函数并且同为true/false,则只触发一次。

3.事件的执行顺序:

    捕获阶段的处理函数最先执行,其次是目标阶段的处理函数,最后是冒泡阶段的处理函数。目标阶段的处理函数,先注册的先执行,后注册的后执行。

4.事件冒泡(由内向外)    事件捕获(由外向内)

5.Dom事件流:三个阶段(捕获阶段,目标阶段,冒泡阶段)

   先调用捕获阶段的处理函数,再调用目标阶段处理函数,再调用冒泡阶段的处理函数。

hml代码:

<div id="outA" style="width: 400px;height: 400px;position: relative;background-color: #080aff">
       <div id="outB" style="width: 400px;height: 400px;position: relative;top:    50px;background-color: #99ffde">
         <div id="outC" style="width: 400px;height: 400px;position: relative;top: 50px;background-color: #b24dff"></div>
      </div>
   </div>

js代码:

<script>

outC.addEventListener('click',function(){console.log('target');},true);
//冒泡
outA.addEventListener('click',function(){console.log('bubble1')},false);
outB.addEventListener('click',function(){console.log('bubble2')},false);
//捕获
outA.addEventListener('click',function(){console.log('capture1')},true);
outB.addEventListener('click',function(){console.log('capture2');},true);

</script>

//结果:capture1,capture2-->target-->bubble1,bubble2

6.阻止事件冒泡:

  outC.addEventListener('click',function(e){console.log('target');
      e.stopPropagation();
       },true);

  outA.addEventListener('click',function(){console.log('bubble1')},false);

  outA.addEventListener('click',function(){console.log('capture1')},true);
//capture1-->target   target之后的被阻止

7.事件委托机制:

 事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

   经典例子:


有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。


这里包含两层意思:

1.现在委托前台的同事是可以代为签收的,即程序中的现有的dom节点是有事件的;

2.新员工也是可以被前台MM代为签收的,即程序中新添加的dom节点也是有事件的。

为什么要用事件委托机制?

      在javascript中,页面中的事件处理程序越多,其与dom元素交互的次数多,访问dom的次数就越频繁,引起了浏览器页面的重绘重排越多,从加长了网页的交互时间。也是提升网页性能之一:减少dom的访问次数。(如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能;   

事件委托栗子1:

<ul id="ull">
    <li>第一个</li>
    <li>第二个</li>
    <li>第三个</li>
</ul>
<script>
    var ull=document.getElementById('ull')
    ull.onclick=function(){
        console.log(123)
    }//将li的时间委托给ul(事件冒泡:由内而外触发)
</script>

栗子2:

<input type="button" value="click me" id="btn6">
<script>
    //event提供了一个事件属性target,可以返回目标事件节点,成为事件源
    //即target可以代表当前的dom,但不是真正的dom
    var btn6=document.getElementById('btn6');
    document.onclick=function(e){
        e=e|| window.e;
        var target= e.target|| e.srcElement;//标准浏览器用ev.target,IE浏览器用event.srcElement,
        if(target==btn6){
            alert(target.value)
        }
    }
</script>

栗子3:

鼠标点击li标签:添加背景色,点击按钮:添加新元素

<input type="button" value="添加" id="btn">
<ul id="ulist">
    <li>111</li>
    <li>222</li>
    <li>333</li>
</ul>

//(1)常规写法:

var btn=document.getElementById('btn');
 var ulist=document.getElementById('ulist');
 var lii=document.getElementsByTagName('li');
 var num=3;
 function func(){
     for(var i=0;i<lii.length;i++){
         lii[i].onclick=function(){
             this.style.backgroundColor='red';
         }
     }
 }
 func();
 btn.onclick=function(){
     num++;
     var lis=document.createElement('li');
     lis.innerHTML=111*num;
     ulist.appendChild(lis);
     func();
 }

//虽然实现了会发现dom的访问次数很多,明显不利于提高网页性能。

//(2)事件委托写法

用事件委托的方法,新添加的元素是带事件的。可以看出事件委托不用for循环遍历li标签,只需对ul设置方法,都可在js代码中执行,大大减少了dom的操作

var btn=document.getElementById('btn');
var ulist=document.getElementById('ulist');
var lii=document.getElementsByTagName('li');
var num=3;
ulist.onclick=function (e){
   var e=e|| window.e;
    var target= e.srcElement|| e.target;
    //元素标签:用nodeName来获取具体是什么标签名,这个返回的是一个大写的,我们需要转成小写再做比较
    //属性名称则不用转直接target.id等
    if(target.nodeName.toLowerCase() == 'li'){
        target.style.backgroundColor='blue';
    }
}
 btn.onclick=function(){
     num++;
     var lis=document.createElement('li');
     lis.innerHTML=111*num;
     ulist.appendChild(lis);
 }

适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。

事件委托优点:

      减少事件注册,节省内存。

      减少dom的操作,提高js代码的运行速度。

事件委托缺点:

     事件委托基于冒泡,对于不冒泡的事件不支持。

    层级过多,冒泡过程中,可能会被某层阻止掉。

理论上委托会导致浏览器频繁调用处理函数,虽然很可能不需要处理。所以建议就近委托,比如在table上代理td,而不是在document上代理td。把所有事件都用代理就可能会出现事件误判。比如,在document中代理了所有button的click事件,另外的人在引用改js时,可能不知道,造成单击button触发了两个click事件。

发布了79 篇原创文章 · 获赞 36 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/yezi__6/article/details/88628380
今日推荐