js事件系列

以前遇到相关的问题都没在意也没深究,常用到的就一个阻止冒泡event.stopPropagation() 每次连单词都是复制过去的。

今天找了几篇相关博客看了下算是理清了,特此总结一下也留个备忘。

 

先说事件流

事件流指从页面中接收事件的顺序,有冒泡流和捕获流。

假如我们点击一个div,实际上是先点击document,然后点击事件传递到div,而且并不会在这个div就停下,div有子元素就还会向下传递,最后又会冒泡传递回document,如下图:

为了兼容更多的浏览器,一般我们都是把事件添加到在事件冒泡阶段。(IE8及以前只支持事件冒泡)。

当dom元素注册多个同种事件,事件发生的顺序按照添加的顺序依次触发(IE是相反的)。

 

添加和删除事件:

DOM事件通过addEventListener(添加)和removeEventListener(删除)管理。

两个方法都一样接收三个参数,第一个是要处理的事件名,第二个是事件处理程序,第三个值为false时表示在冒泡阶段调用处理程序,一般建议在冒泡阶段使用。

IE则用attachEvent(),detachEvent(),接收两个参数,事件名称和事件处理程序,通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段。

 

事件对象event:

当触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含了所有与事件有关的信息。

比如导致事件的元素target,只有在事件处理程序执行期间,event对象才会存在,一旦事件处理程序执行完毕,event对象就会被销毁。

在事件处理程序中this === event.target

在IE中event参数是未定的,事件对象是作为window的一个属性存在的,因此可以通过window.event来访问event对象,不同于DOM级中event是作为参数直接传入和返回。

 

事件冒泡和事件捕获:

他们是描述事件触发时序问题的术语。

事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件。

相反事件冒泡是自下而上的去触发事件。

绑定事件方法的第三个参数,就是控制事件触发顺序是否为事件捕获。

true-事件捕获,false-事件冒泡,默认false,即事件冒泡。

 

下面是demo演示冒泡和捕获:

<div id="parent">
  <div id="child" class="child"></div>
</div>
/////////
document.getElementById("parent").addEventListener("click",function(e){
  alert("parent事件被触发,"+this.id);
}, false)
document.getElementById("child").addEventListener("click",function(e){
  alert("child事件被触发,"+this.id)
}, false)

上面打印结果:

child事件被触发,child

parent事件被触发,parent

因为第三个参数是false所以是事件冒泡 就会先触发里面dom元素。

如果改为true则结果相反。

 

阻止事件冒泡捕获:

event.stopPropagation()不能简单说阻止了事件的冒泡,其实也阻止了事件的继续捕获,确切的说应该是阻止事件的进一步传播。

d1.addEventListener('click', function (event) {
  console.log('d1');
  event.stopPropagation();
}, true);

 

事件委托:

也可以称为事件代理。用到这个是为了减少不必要的事件处理程序,达到性能优化减少内存的作用。

用法如下:

// 相同任务时
window.onload = function(){
  var oUl = document.getElementById("ul1");
  oUl.onclick = function(ev){
    var ev = ev || window.event;
    var target = ev.target || ev.srcElement;
    if(target.nodeName.toLowerCase() == 'li'){
          alert(123);
         alert(target.innerHTML);
    }
  }
}

上面用父级ul做事件处理,当li被点击时,由于冒泡原理,事件就会冒泡到ul上,因为ul上有点击事件,所以事件就会触发,当然,这里当点击ul的时候,也是会触发的。

// 不同任务时
window.onload = function(){
    var oBox = document.getElementById("box");
    oBox.onclick = function (ev) {
        var ev = ev || window.event;
        var target = ev.target || ev.srcElement;
        if(target.nodeName.toLocaleLowerCase() == 'input'){
            switch(target.id){
                case 'add' :
                    alert('添加');
                    break;
                case 'remove' :
                    alert('删除');
                    break;
                case 'move' :
                    alert('移动');
                    break;
                case 'select' :
                    alert('选择');
                    break;
            }
        }
    }
    
}

 

posted @ 2018-11-09 17:39  GR07  阅读(203)  评论(0编辑  收藏  举报