JavaScript之事件对象Event(事件)

事件

事件:用户与浏览器特定的交互瞬间。

事件对象

在触发DOM上的事件时,会产生一个事件对象Event,它包含了与事件相关的所有信息。如:事件的类型、导致事件的元素(当前元素)、以及其它与事件相关的信息。如鼠标操作事件中,包含了鼠标的位置。键盘操作事件中,包含了是否敲击了键盘等。

DOM中的事件对象


兼容DOM的浏览器会将 事件对象Event 传入事件处理程序中,无论指定事件处理程序的方式是什么(DOM 0级、DOM 2级或HTML特性)。

<body>
  
  <input id="input1" type="button" value="单击事件">
  
  <script>

      var input1 = document.getElementById("input1");

      var event = function (e) {
	      alert(e.type);
	  };

	  
      input1.onclick = event; //click

      input1.addEventListener("click", event, false); //click
</script>
</body>

弹出事件的类型为"click"事件。


对于HTML特性指定的事件处理程序

<input id="input1" type="button" value="单击事件" οnclick="alert(event.type);">




在事件处理程序内部,对象this始终等于currentTarget(当前正在处理事件的那个元素),而target表示实际目标(即当前元素)。

当事件处理程序直接指定给input按钮时,
<body>
  
  <input id="input1" type="button" value="单击事件" οnclick="alert(event.type);">
  
  <script>

      var input1 = document.getElementById("input1");

      var event = function (e) {
	      alert(e.currentTarget === this); //true
              alert(e.target === this); //true
	  };

	  
      input1.onclick = event; //true

      
</script>
</body>
这个例子是直接将事件处理程序指定给了当前元素(即input)。因此this、target、currentTarget这三个值是相等的。


如果 事件处理程序在按钮的父节点(如:document.body)中:

第一种情况,当我们 直接点击按钮时,
<body>
  <input id="inpt1" type="button" width="100px" value="单击事件">
  <script>
     var inpt1 = document.querySelector("#inpt1");
     
     //直接将事件处理程序指定给当前元素,即input按钮。
     inpt1.onclick = function (e){
         console.log(e.currentTarget === this); //true 处理事件的就是input按钮
         console.log(this.type);  // button
         console.log(e.target === this); //true 事件的真正目标就是input按钮
     };
     
     //将事件处理程序指定给父级节点。
     document.body.onclick = function (e){
         console.log(e.currentTarget === document.body); // true 处理事件的是document.body
         console.log(document.body === this); //true this等于currentTarget,此时为document.body
         console.log(e.target === this); // false
         console.log(e.target === inpt1); //true 事件的真正目标就是input按钮。
         console.log(e.target === document.body); //false 事件的真正目标就是input按钮。不是document.body
     };
   
   </script>
</body>

效果:


我们可以看到,当直接点击按钮时,就会在input按钮和document.body上均触发onclick事件。当将事件处理程序指定给input按钮时,currentTarget、this、target的值都是当前元素(input按钮),处理事件的就是input按钮,事件的真正目标是input按钮。当将事件处理程序指定给其document.body时,this === currentTarget,此时处理事件的是document.body,而这个事件的真正目标还是input按钮。


第二种情况,当我们点击input按钮即点击body内部时:效果就不一样了
<body>
  <input id="inpt1" type="button" width="100px" value="单击事件">
  <div>撑开body</div>
  <div>撑开body</div>
  <script>
     var inpt1 = document.querySelector("#inpt1");
     
     //此时不触发
     inpt1.onclick = function (e){
         console.log(e.currentTarget === this); 
         console.log(this.type);  // button
         console.log(e.target === this); 
     };
     
     //当点击body内部时,是body在处理事件,在document.body上触发
     document.body.onclick = function (e){
         console.log(e.currentTarget === document.body); // true 处理事件的是document.body
         console.log(document.body === this); //true this等于currentTarget,此时为document.body
         console.log(e.target === this); // true
         console.log(e.target === inpt1); //false 事件的真正目标就是input按钮。
         console.log(e.target === document.body); //true 事件的真正目标就是input按钮。不是document.body
     };
   
   </script>
</body>

效果:



此时,我们可以看到,当点击body内部除input按钮之外的地方时,就会在document.body上触发事件,此时,this===currentTarget===document.body,处理事件的是document.body, 注,此时事件的真正目标就是document.body,因为按钮没有触发事件,即e.target===document.body。




有时需要一个函数处理多个事件,因此可以利用 开关语句 为其添加事件。
var input1 = document.getElementById("input1");

var event = function (e) {
    switch (e.type) {
        case "click":
             alert("clicked");
             break;
        case "mouseover":
              e.target.style.color = "red"; //当前元素的颜色变成红色
              breadk;
        case "mouseout":
              e.target.style.color = "blue";
    }
};

input1.oclick = event;
input1.mouseover = event;
input1.mouseout = event;


先要判断事件的类型,再执行相应操作。



想要阻止事件的默认行为,可以使用preventDefult()方法来取消事件的默认行为。如:<a>超链接,点击超链接时,会默认跳转到指定的ULR页面。可以用perventDefult()来取消这种行为。

var a1 = document.getElementById("a1");

a1.onclick = function (e) {
    e.preventDefult(); //阻止了a元素默认的跳转行为,点出不会跳转
};


当然,只有cancelable属性的值为true的情况下,才能使用preventDefult()来取消默认的行为。



stopPropagation()停止事件在DOM层次中传播,也就是取消进一步事件捕获或冒泡。

var a1 = document.getElementById("a1");

a1.onclick = function (e) {
    alert("hi");
    e.stopProPagation(); //取消事件继续在DOM层次中传播
};
//取消了传播,下列代码不会执行
document.body.onclick = function (e) {
    alert("HI");
};

本来要出现两个警告框的,但通过stopPropagation()已经取消了事件继续在DOM层次中传播,onlcick事件也就不会传播(冒泡)到document.body这里来,因此不会触发注册到document.body上的事件处理程序了,document,body也就不会处理事件了。



eventPhase属性来确定当前事件在哪个阶段了,返回1表示处于捕获阶段,返回2表示事件处理程序处于目标对象上,返回3表示处于冒泡阶段。虽然“处于目标”发生在冒泡阶段,但会返回2。
<body>
  <input id="inpt1" type="button" width="100px" value="单击事件">
  <div>撑开body</div>
  <div>撑开body</div>
  <script>
     var inpt1 = document.querySelector("#inpt1");
     
     //事件处于目标上
     inpt1.onclick = function (e){
         console.log("返回:" + e.eventPhase + "表示事件处于目标上"); //2
     };
     //捕获阶段,布尔值为true     
     document.body.addEventListener("click", function (e) {
         console.log("返回:" + e.eventPhase + "表示事件处于捕获阶段"); //3
     }, true);
     //冒泡阶段,也就是事件从目标向上传播了。
     document.body.onclick = function (e) {
         console.log("返回:" + e.eventPhase + "表示事件处于冒泡阶段"); //1
     };
   
   </script>
</body>

效果:


从这个例子中,我们发现, 当我们点出按钮时,会触发事件的三个阶段,即第一阶段捕获阶段,第二阶段事件处于目标上,第三阶段冒泡阶段。但 当我们点出body内部除了按钮之外的地方时,只会触发事件的二个阶段,分别是第一阶段捕获阶段,第三阶段冒泡阶段,这是因为此时没有点出按钮,那么按钮就不会触发事件处理程序,触发事件的是document.body,也就是说document.body在处理事件,即target===this==currentTarget===document.body。



IE中的事件对象

与访问DOM中的event对象不同的是,IE中访问event对象取决于指定 事件处理程序 的方式(DOM 0级、IE特有的、HTML特性)。 在IE中,event对象是未定义的,也就是undefined,返回的是window.event。

使用DOM 0级指定事件处理程序时,event对象是作为window对象的属性来看的。

var input1 = document.getElementById("input1");

input1.onclick = function () { //
    var event = window.event; //全局对象的属性,所以不用传递参数。
    alert(event.type); //click
};

可以这样理解:IE中的window.event相当于DOM中的event。且DOM 0级中,IE无需传入event作为参数。


而对于用attachEvent()方法指定事件处理程序,将event对象作为参数传入事件处理函数。

var input1 = document.getElementById("input1");

input1.attachEvent("onclick", function (event) { //传入参数
    alert(event.type); //click
});

用这种方法指定事件处理程序,与在DOM中用addEventListener()指定一样,将event对象作为参数传入事件处理函数。


用HTML特性指定事件处理程序,可以通过event变量来访问event对象(与在DOM中用HTML特性指定一样)。

<input id="input1" type="button" value="单击事件" οnclick="alert(event.type);">



在IE中,用srcElement来表示事件的目标(与DOM中target一样)。

var input1 = document.getElementById("input1");

//DOM 0级方式
input1.onclick  = function () { //在IE中使用DOM 0级,无需传入参数
    alert(window.event.srcElement === this); //true
};

在前面已经提过:在IE中 通过attachEvent()添加事件,事件处理程序是在全局作用域运行的,也就是this对象指向window对象,属于全局对象
var inpt1 = document.querySelector("#inpt1");
inpt1.attachEvent("onclick", function (e) {
    alert(e.srcElement == this); //false 此时this对象指向window对象,事件目标日显不是全局对象。
});

通过attachEvent()方法添加事件,this属于全局对象,指向widow了,不再指向当前元素(inpt1)了,那么srcElement事件目标指向的不是this了,而应该是当前元素(inpt1):
var inpt1 = document.querySelector("#inpt1");
inpt1.attachEvent("onclick", function (e) {
    alert(e.srcElement == inpt1); //true 
});




在IE中,用returnValue来阻止事件的默认行为。与DOM中的perventDefult()方法一样的效果。不过,returnValue要赋值false才有效果。

var input1 = document.getElementById("input1");

//DOM 0级方式
input1.onclick = function () {
    window.event.returnValue = false; //阻止IE中事件的默认行为
};


在IE中,用canceBubble来停止事件在DOM层次中继续传播。与DOM中的stopPropagation()方法一样的效果。不过,要给canceBubble赋值true才有效果。

当然,IE中只有事件冒泡,所以就是停止事件冒泡的继续传播。

var input1 = document.getElementById("input1");

//事件处于目标上阶段
input1.onclick = function () {
    alert("hi"); 
    window.event.canceBubble = true; //停止事件在DOM层次中继续传播,也就是停止事件冒泡。
};
//事件冒泡阶段
document.body.onclick = function () {
    alert("HI");
};

本来要出现两个警告框的,但通过canceBubble已经取消了事件继续在DOM层次中传播,所以,也就不会传播到document.body这是来了。停止通过冒泡触发document.body中注册的事件处理程序。



跨浏览器的事件对象(event)

IE中的event与DOM的event不同,但IE中event对象的全部信息和方法在DOM中也有,所以可以根据它们的相似性做跨浏览器的方法来。将前面提到的EventUtil对象加强即可。

加强后的EventUtil对象:

var EventUtil = {
    //添加事件句柄
    addHandler : function (element, type, handler) {
		  
        //DOM 2级事件处理程序  
        if (element.addEventListener) {
            element.addEventListener(type, handler, false);
        } else if (element.attachEvent) { // IE事件处理程序
            element.attachEvent("on" + type, handler);
        } else {
            
            //将当前元素看作对象,引用事件处理程序这个属性
            element["on" + type] = handler; // DOM 0级事件处理程序
        }
    },

    //获取event对象
    getEvent : function (event) {
        //利用条件赋值操作符来确定event,如果支持event,则返回DOM中event对象,如果不支持则返回IE中的event对象
        return event ? event : window.event
    },
    //定义getDefult方法,用于阻止事件的默认行为
    getDefult : function (event) {
        if (event.preventDefult) {
            event.preventDefult();
        } else {
            window.event.returnValue = false;
        }
    },
    //定义getTarget方法,用于获取实际目标
    getTarget : function (event) {
        return event.target || event.srcElement;
    }


		  
    //这是删除事件
    removeHandler : function (element, type, handler) {
        if (element.removeEventListener) {
            element.removeEventListener(type, handler, false);
        } else if (element.detachEvent) {
            element.detachEvent("on" + type, handler);
        } else {
            element["on" + type] = null; //DOM 0级删除事件赋值null给事件处理程序名即可。
        }
    },
    //定义stopPropagation方法,用于停止事件继续向DOM层次传播
    stopPropagaton : function (event) {
        if (event.stopPropagation) {
            event.stopPropagation();
        } else {
            event.canceBubble = true;
        }
    }
};


在兼容DOM的浏览器中,返回事件对象Event
var input1 = document.getElementById("input1");

input1.onclick = function (event) {
    event = EventUtil.getEvent(event); //这里返回的是event.
};


在IE中,event是未定义的,也就是undefined,返回的是window.event.
var input1 = document.getElementById("input1");

input1.onclick = function () {
    event = EventUtil.getEvent(event); //这里返回的是window.event
};


返回事件目标。
var input1 = document.getElementById("input1");

input1.onclick = function (event) {
    var target = EventUtil.getTarget(event);
};


想要返回什么,就可以用EventUtil对象调用其属性即可。是得到event对象,还是阻止默认行为,或者是停止事件的传播均可。



关于Event对象,再多说一句:

在兼容DOM中的Event参数,只是简单地传入和返回;而在IE中的Event参数是未定义的,也就是undefined,返回的是window.event。



  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值