事件基础
什么是事件?
事件分为两部分:
1)行为本身:浏览器天生就赋予其的行为。onclick、onmouseover(onmouseenter)、onmouseout(onmouseleave)、onmousemove、onmousedown、onmouseup、onmousewheel(鼠标滚轮滚动行为)、onscroll(滚动条滚动行为)、onresize(window.onresize浏览器窗口的大小改变事件)、onload、onunload(window.onunload关闭窗口)、onfocus(文本框获取焦点行为)、onblur(文本框失去焦点行为)、onkeydown/onkeyup(键盘的按下和抬起行为)…
哪怕我没有给上述的行为绑定方法,事件也是存在的,当我们点击这个盒子的时候,同样会触发它的onclick行为,只是什么事情都没做而已。
onmouseover(onmouseout)和onmouseenter(onmouseleave )的区别
:
他们都是鼠标滑上去的行为,但是onmouseenter浏览器默认组织了它的冒泡传播;而onmouseover是存在冒泡传播的,想要阻止的话只能自己写代码阻止。
2)事件绑定:给元素的某一个行为绑定方法。
// DOM0级事件绑定。 div.onclick = function(e){ // 当我们触发div的click行为的时候,会把绑定的这个函数执行 e = e || window.event; e.type // 存储的是当前鼠标触发的行为类型 “click” e.clientX / e.clientY // 当前鼠标触发点距离当前屏幕左上角的x/y轴的坐标值。 e.targe // 事件源,当前鼠标触发的是哪个元素,那么它存储的就是哪个元素。但是在IE6-8中不存在这个属性(e.target的值是undefined,我们使用e.srcElement来获取事件源)。 e.target = e.target || e.srcElement; e.pageX / e.pageY // 当前鼠标触发点距离body左上角(页面第一屏幕最上端)的x/y轴坐标。但是在IE6-8中没有这个属性,我们通过使用clientY+滚动条卷去的高度来获取也可以。 e.pageX = e.pageX || (e.clientX+(document.documentElement.scrollLeft || document.body.scrollLeft)); e.pageY = e.pageY || (e.clientY+(document.documentElement.scrollTop || document.body.scrollTop)); e.preventDefault() // 阻止浏览器的默认行为(比如a标签,默认行为是跳转页面)。在IE6-8中没有这个方法。 e.preventDefault ? e.preventDefault() : e.returnValue = false; // 或者直接return false;和上述代码是一样的效果,也能组织默认行为。 // 或者在HTML结构上组织默认行为 href="javascript:;" / href="javascript: void 0;" / href="javascript: void 1;" e.stopPropagation() // 阻止事件的冒泡传播,在IE6-8下不兼容,使用 e.cancelBubble = true //来代替。 console.log(e); };
onclick这个行为定义在当前元素的私有属性上。
我们是把匿名函数定义的部分当做一个值赋值给div的点击行为(函数表达式)。
当我们触发div的点击行为的时候,会执行对应绑定上的方法
注意:
1、不仅仅把绑定的方法执行了,而且浏览器还默认给这个方法传递了一个参数值=>MouseEvent:鼠标事件对象。
1)MouseEvent是一个对象数据类型值,里面包含了很多属性名和属性值,这些都是用来记录当前鼠标的相关信息的。
2)MouseEvent–>UIEvent–>Event–>Object
3)MouseEvent记录的屙屎页面中唯一一个鼠标每一次触发时候的相关信息,和到底是在哪个元素上触发的没有关系。
2、关于事件对象MouseEvent的兼容问题
1)事件对象本身的获取存在兼容问题:标准浏览器中是浏览器给方法传递的参数,我们只需要定义形参e就可以获取到;在IE6-8中浏览器不会给方法传递参数,我们如果需要的话,需要到window.event中获取查找。 --> e = e || window.event;// DOM2级事件绑定 div.addEventListener("click", function(){ },false); // addEventListener这个属性是定义在当前元素所属EventTarget这个类的原型上的
var input1 = document.getElementById("input1"); input1.onkeyup = function (e) { e = e || window.event; // KeyBoardEvent e.keyCode // 当前键盘上每一个键对应的值 // 空格键(space)=>32 // 回退键(Backspace)=>8 // 回车键(Enter)=>13 // 删除键(Del)=>46 // 四个方向键=> 左(37) 上(38) 右(39) 下(40) } document.body.onkeyup = function(e){ }
事件传播机制
事件委托
什么是事件委托/事件代理?
利用事件的冒泡传播机制(触发当前元素的某个行为,它父级所有元素的相关行为都会被触发),如果一个容器中有很多元素都要绑定点击事件,我们没有必要一个个绑定了,只需要给最外层容器绑定一个点击事件即可,在这个方法执行的时候,通过事件源(e.target)的区分来进行不同的操作。
DOM2级事件
1、 DOM0级事件和DOM2级事件的区别:
1、DOM0级事件绑定:只能给一个元素的某一个事件绑定一次方法,第二次绑定的会把前面的覆盖掉。
2、我们使用DOM2级事件绑定,其实是让box通过原型链一直找到EventTarget这个内置类原型上的addEventListener方法实现的。// DOM2级事件绑定 div.addEventListener("click", function(){ console.log(1); },false); div.addEventListener("click", function(){ console.log(2); },false); // 点击的时候两个方法都会被触发
- DOM2可以给某一个元素的同一个行为绑定多个不同的方法。
- DOM0中的行为类型,我们用DOM2都可以绑定,而DOM2中还提供了一些DOM0没有的行为类型=>DOMContentLoaded:当页面中的DOM结构(HTML结构)加载完成触发的行为。
document.addEventListener("DOMContentLoaded", function(){ }, false);
window.onload = function(){} =>当页面中的所有资源(图片、HTML结构、音视频)都加载完成才会执行后面的函数;并且在一个页面中只能用一次,后面再写会把前面的覆盖掉。因为采用DOM0事件绑定,所以只能绑定一次。
jQuery: ( d o c u m e n t ) . r e a d y ( f u n c t i o n ( ) ) = > (document).ready(function(){})=> (document).ready(function())=>(function(){}) 只要当页面中的HTML结构加载完成就会执行对应的函数;并且在同一个页面中可以出现多次;所以采用DOM2事件绑定,并且绑定的行为是DOM2中新增加的DOMContentLoaded。
2、DOM2
1)在使用DOM2绑定的时候,我们一般都给它绑定的是实名函数。
function fn1(e){
console.log(this); // this=>box
}
box.addEventListener("click", fn1,false);
// 移除的时候需要保证三个参数:行为、方法、哪个阶段发生,一点都不能差
box.removeEventListener("click", fn1, false);
2)标准浏览器的事件池机制
:
- 重复问题:只能给某个元素的同一个行为绑定多个
不同
的方法(如果方法相同了只能留一个)。 - 顺序问题:当行为触发,
会按照绑定的先后顺序依次把绑定的方法执行
。 - this问题:执行的方法中的this是当前被绑定事件的元素本身。
注意:
DOM2事件池机制的兼容性问题:
在IE6-8浏览器中,不支持addEventListener /
removeEventListener,如果想实现DOM2事件绑定,只能用attachEvent / detachEvent:
- 它只有两个参数,不能像addEventListener那样控制在哪个阶段发生,默认只能在冒泡阶段发生。
- 行为需要添加“on”(和DOM0特别类似)。
box.attachEvent("onclick", fn1); box.attachEvent("onclick", fn2); box.attachEvent("onclick", fn3); box.attachEvent("onclick", fn4);
和标准浏览器的事件池机制对比:
1、顺序问题:执行的时候顺序使混乱的,标准浏览器是按照绑定顺序依次执行的。
2、重复问题:可以给同一个元素的同一个行为绑定多个相同的方法。
3、this问题:IE6-8中,当方法执行的时候,方法中的this不是当前的元素box,而是window。
3、事件池:是用来存储当前元素行为绑定的方法的(浏览器天生自带的机制)。