JavaScript之事件对象Event(事件)

    xiaoxiao2021-04-16  39

    事件

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

    事件对象

    在触发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。
    转载请注明原文地址: https://ju.6miu.com/read-673096.html

    最新回复(0)