事件||事件流||通用事件侦听器函数

事件||事件流||通用事件侦听器函数

一、跨浏览器事件对象:

事件流:描述的是从页面中接收事件的顺序。

IE:的事件流是事件冒泡流。javascript

事件冒泡(event bubbling):事件由最具体的元素(嵌套最深的那个节点)接收,而后逐级向上传播到不具体的节点(文档)。明显的缺点就是在多个子元素上绑定事件,父元素节点会接受到全部的事件绑定,这是个很坑爹的体验。html

Netscape Communicator:的事件流是事件捕获流。java

事件捕获(event capuring):是不太具体的元素节点应该更早的接收到事件,而更具体的节点应该最后接收到事件。符合经常使用的模型和思考方式。chrome

Dom事件流:“Dom2级事件”规定了事件流包括三个阶段。(事件代理处理)浏览器

事件捕获阶段、处于事件阶段和事件冒泡阶段即事件捕获为截获事件提供了机会接着实际的目标接收到事件最后冒泡阶段,在这个阶段对事件作出响应dom

实际上这里已经显示了捕获要在冒泡以前。函数

大多的时候会把事件流添加到冒泡阶段,这样能够最大限度的兼容各类浏览器。此时DOM2级事件设为false。this

这里的捕获阶段不涉及事件目标。这个时候的事件冒泡或者是事件捕获使用,添加事件最后的限定true(捕获阶段)||false(冒泡阶段)来触发。若是不写是根据浏览器的特性来实现的。url

以下来验证:一个DOM元素绑定两个事件,一个冒泡,一个捕获,则事件会执行多少次,执行顺序如何。先捕获后冒泡。spa

//以下事件冒泡阶段触发
<div id='one'>1
  <div id='two'>2
    <div id='three'>3
      <div id='four'>4
      </div>
    </div>
  </div>
</div>
<script type='text/javascript'>
  var one=document.getElementById('one');
  var two=document.getElementById('two');
  var three=document.getElementById('three');
  var four=document.getElementById('four');
  one.addEventListener('click',function(){
    alert('one');
  },false);//表示在冒泡阶段触发事件
  two.addEventListener('click',function(){
    alert('two');
  },false);
  three.addEventListener('click',function(){
    alert('three');
  },false);
  four.addEventListener('click',function(){
    alert('four');
  },false);
</script>

//点击4,依次会触发four、three、two、one。
<div id='one'>1
  <div id='two'>2
    <div id='three'>3
      <div id='four'>4
      </div>
    </div>
  </div>
</div>
<script type='text/javascript'>
  var one=document.getElementById('one');
  var two=document.getElementById('two');
  var three=document.getElementById('three');
  var four=document.getElementById('four');
  one.addEventListener('click',function(){
    alert('one');
  },true);//表示在捕获阶段触发事件
  two.addEventListener('click',function(){
    alert('two');
  },true);
  three.addEventListener('click',function(){
    alert('three');
  },true);
  four.addEventListener('click',function(){
    alert('four');
  },true);
</script>
//点击4则依次触发:one、two、three、four
<div id='one'>1
  <div id='two'>2
    <div id='three'>3
      <div id='four'>4
      </div>
    </div>
  </div>
</div>
<script type='text/javascript'>
  var one=document.getElementById('one');
  var two=document.getElementById('two');
  var three=document.getElementById('three');
  var four=document.getElementById('four');
    one.addEventListener('click',function(){
      alert('one');
    },true);
    two.addEventListener('click',function(){
      alert('two,bubble');
    },false);//这里的事件在冒泡阶段触发
    two.addEventListener('click',function(){
      alert('two,capture');
    },true);//这里的事件在捕获阶段触发
    three.addEventListener('click',function(){
      alert('three,bubble');
    },true);
    four.addEventListener('click',function(){
      alert('four');
    },true);
</script>
<!-- 执行顺序最终结果是:(chrome先捕获后冒泡)点击4,依次会触发 one、two,capture、three,bubble、four、two,bubble-->
<!-- 说明,同一个元素上绑定事件是先捕获,再冒泡。中间还有一个处于目标阶段 -->

二、事件处理程序(事件侦听器):

事件是用户或浏览器自身执行的某种动做:如click、load、mouseover等,响应某个事件的函数称为事件处理程序(事件监听器)

一、html事件处理程序

事件处理程序中的代码在执行时,有权访问全局做用域中的任何代码(匿名函数的做用域-全局)。

直接写在页面元素中,强耦合,摒弃。页面在前解析,js在后解析。

存在时差问题,可能在处理程序解析以前就触发了事件,会致使错误。

MouseEvent对象以下:

<input type="button" value = "click me" onclick = "console.log(event)"/>

这里的path保存着事件冒泡的顺序(具体到不具体),target保存着目标节点的信息,view保存着window对象的一些信息。

二、Dom0级事件处理程序(onclick): 

经过JavaScript指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。这种方法被称为事件处理程序赋值,出如今第四代 Web 浏览器中。

每一个元素(包括 window 和 document)都有本身的事件处理程序属性,属性一般所有小写,如 onclick。将这种属性的值设置为一个函数,就能够指定事件处理程序。

<input type="button" value = "Dom0" id = "myBtn" />
<script type="text/javascript">
    var btn = document.getElementById("myBtn");
    btn.onclick = function(event){
        console.log(event);
    }
</script>

打印结果与上边无差。处理函数内部this指向元素节点。能够取到this.id。

删除事件,将事件处理函数置为null便可。

btn.onclick = null;

三、Dom2级事件处理程序(事件绑定与取消绑定):

“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操做:addEventListener()和removeEventListener() ;

它们接受3个参数:

  1. 要处理的事件名

  2. 做为事件处理程序的函数

  3. 一个布尔值:

    true: 捕获阶段调用事件处理程序

    false: 冒泡阶段调用

<input type="button" value = "Dom2" id = "myBtn2" />
<script type="text/javascript">
    var btn = document.getElementById("myBtn2");
    btn.addEventListener("click",function(event){
        alert("Dom2");
        console.log(event);
    },false);
</script>

事件event与以前的无差。

能够添加多个事件,添加多个事件的时候,按添加的顺序依次执行。

移除事件要一一对应,注意因为匿名函数在内存中没有指向对象,因此添加以后没法移除因此作好的作法就是先定义好声明的处理函数(或者函数表达式),在进行绑定和删除。

大部分时候都是把事件添加到冒泡(false)阶段,这样能够最大限度的兼容各类浏览器。

四、IE事件处理程序: 

IE 实现了与 DOM 中相似的两个方法:attachEvent()和detachEvent() 

接受两个参数:事件处理程序名称、事件处理程序函数 

经过这种方法添加的事件处理程序会被添加到冒泡阶段。 

<input type="button" value = "IE" id = "myBtn3" />
<script type="text/javascript">
    var btn = document.getElementById("myBtn3");
    btn.attachEvent("onclick",function(event){
        alert("Clicked");
        console.log(event);
        console.log(this)
    });
</script>

打印的结果不能展开:

在IE中使用 attachEvent() 与使用 DOM0 级方法的主要区别在于事件处理程序的做用域。

DOM0 级方法:在Dom0级事件当中,事件处理程序会在其所属的元素的做用于内运行。

attachEvent()方法:使用attachEvent()方法的状况下,事件处理程序会在全局做用域中运行。此时this 等于window。

固然,匿名函数不能被移除。

五、事件对象:

触发Dom上的某个事件的时候,会产生一个事件对象event,这个对象包含着与事件相关的信息,包含致使事件的元素、事件的类型及其余信息。

event对象包含着与建立它的特定事件有关的属性和方法。

Dom中的事件对象:

事件对象的一些属性和方法:

主要的有:

cancelable:代表是否能够取消事件默认行为。

currentTarget:时间处理程序当前正在处理的那个元素处理程序内部,对象this始终等于currentTarget的值。而target只包含事件的实际目标。

preventDefault():取消事件的默认行为

target:事件目标。

stopPropagation(): 取消事件进一步的捕获或者冒泡

只有在执行事件期间,event才存在,事件执行完成以后,event对象就会被销毁。

IE事件对象中有区别的地方:

三、通用事件监听函数

//写一个通用的事件侦听器函数 //跨浏览器事件对象
var EventUtil = {
    //页面加载完成以后,页面彻底加载以后执行。
    readyEvent:function(fn){  
        if(document.addEventListener){      
            //标准浏览器  
            document.addEventListener('DOMContentLoaded',function(){  
                //注销事件,避免反复触发  
                document.removeEventListener('DOMContentLoaded',arguments.callee,false); 
                //执行函数   
                fn();
            },false);  
        }else if(document.attachEvent){     
            //IE浏览器  
            document.attachEvent('onreadystatechange',function(){  
                if(document.readyState=='complete'){  
                    document.detachEvent('onreadystatechange',arguments.callee);  
                    //执行函数   
                    fn();  
                }  
            });  
        }  
    },
    /*
     *attachEvent可使用匿名函数,但这样以后,detachEvent将没法卸载之。
     *detachEvent所卸载的函数必须使用函数名。
     */
    //添加事件
    addEvent:function(element,type,handler){
        if(element.addEventListener){//非IE,DOM2
            //事件类型、须要执行的函数、是否捕获
            element.addEventListener(type,handler,false);
        }else if(element.attachEvent){//IE
            element.attachEvent('on'+type,handler);
        }else{
            element['on'+type] = handler;//DOM0
        }
    },
    //移除事件
    removeEvent:function(element,type,handler){
        if(element.removeEventListener){
            element.removeEventListener(type,handler,false);
        }else if(element.detachEvent){
            element.detach('on'+type,handler);
        }else{
            element['on'+type] = null;
        }
    },
    //阻止事件冒泡(主要是事件冒泡,由于IE不支持事件捕获),用于当即中止事件在Dom层中的传播,即进一步取消事件的捕获或者冒泡。
    stopPropagation:function(event){
        if(event.stopPropagation){
            event.stopPropagation();//W3C标准
        }else{
            event.canceBubble = true;//IE
        }
    },
    //取消事件的默认行为, 如url的跳转等
    preventDefault:function(event){
        if(event.preventDefault){
            event.preventDefault();//W3C标准
        }else{
            event.returnValue = false;//IE
        }
    },
    //获取事件目标
    getTarget:function(event){
        return event.target||event.srcElement;
    },
    //获取event对象的引用,获取事件的全部信息,确保随时能使用event;
    getEvent:function(event){
        var event = event||window.event;//在Dom0级事件添加,event做为window对象的一个属性存在。
    }
};
// 定义一个函数处理多种类型的事件
var handler = function(event){
    switch(event.type){
        case "click":
            alert("Clicked");
            break;
        case "mouseover":
            event.target.style.backgroundColor = "red";
            break;
        case "mouseout":
            event.target.style.backgroundColor = "";
            break;
        default:
            alert("test switch");
    }
};
//阻止事件冒泡的实例
var btnCancel = document.getElementById("btnCancel");
btnCancel.onclick = function(event){
    alert("clicked222");    
    //这样以后,body上的事件就不会触发了,否则点一下,就会触发这两个事件。
    EventUtil.stopPropagation(event);
};

document.body.onclick = function(event){
    //若是btnCancle上阻止了事件冒泡,那么body上的事件就不会被添加到btnCancle上。
    alert("body clicked")
}
获取一组元素的序号,原理是本身先要获取元素而后添加属性到标签中。点击事件的时候再获取自定义的属性。
两种方法,标签添加属性和使用自定义属性。
另:Dom0型事件的处理函数的this 等于 event.target属性。

<ul >
    <li class="a1">1</li>
    <li class="a2">2</li>
    <li class="a3">3</li>
    <li class="a4">4</li>
    <li class="a5">5</li>
    <li class="a6">6</li>
</ul>

var list = document.getElementsByTagName("li");
for(var i = 0,len = list.length;i<len;i++){
    list[i].index = i;//方法1,比较好
    list[i].setAttribute("data-index",i);//方法2
    list[i].onclick = function(event){
        console.log(this.getAttribute("data-index"));
        console.log(this.index);
        console.log(event);
        console.log(this==event.target);
    }
}

//固然事件也是能够绑定到父元素上
var ul = document.getElementsByTagName("ul");
ul[0].onclick = function(event){
    console.log(event.target.index);
}

IE事件与FF(DOM)事件的区别:

一、window.event

表示当前的事件对象,IE的事件对象是window对象的一个属性。 FF:没有window.event对象。能够经过给函数的参数传递event对象。如onmousemove=domousemove(event)。

二、获取事件源

IE:srcElement;FF:target;

三、添加删除事件方法不一样

IE:element.attachEvent("onclick",function(){})

FF: element.addEventListener("click",function(){},false);

删除事件也是不一样的。

四、自定义DOM事件

自定义DOM事件不是由DOM原生触发的,目的是让开发人员建立本身的事件。建立自定义事件,须要调用createEvent("CustomEvent");

且看以下实例:

var div = document.getElementById("myDiv");

var event;
EventUtil.addHandler(div,"myevent",function(event){
  alert("DIV:   " + event.detail);
});
EventUtil.addHandler(document,"myevent",function(event){
  alert("DOCUMENT:   " + event.detail);
});

if(document.implementation.hasFeature("CustomEvents","3.0")){
  event = document.createEvent("CustomEvent");
  event.initCustomEvent("myevent",true,false,"hello world!");//对应参数:触发事件类型、事件是否冒泡、事件是否能够取消、任意值,保留在event对象的detail中
  div.dispatchEvent(event);
}

事件代理:

事件代理,具体实例,上边的ul元素绑定index,能够用。

相关文章
相关标签/搜索