目录
4. 方法四:IE下使用attachEvent/detachEvent函数进行事件绑定
一、事件
事件:就是函数在某种状态下/事件触发时(浏览器设置的)被调用.JS捕捉到的发生在网页上的行为,官方称为事件句柄,是交互体验的核心功能
事件的三要素: 1 事件源 2 事件类型 3 事件处理程序(handler)
var box = document.querySelector(".box")
box.onclick = function() { //onclick是点击事件,后面的function是处理程序
console.log("你购买了装备")
}
二、绑定事件(事件的写法4种)
1.方法一:行内绑定方式
在标签行内 的事件值上写上标志"javaScript:后跟js代码"
标签的属性值时事件触发时执行代码。行内式可以绑多个,因为后面是代码执行体
<a href="javaScript:alert(666)">点我</a>
<a href="javaScript:void(0)">点我</a>
<button onclick="javaScript:alert(666)">点我</button>
<div class="box1" onclick="javaScript:myconsole.mylog()">hello</div> //111
//<div class="box1" onclick="myconsole.mylog()">hello</div> //不写javaScript也可以
<div class="box2" onclick="fn()">hello</div> //222 这种写法的好处: 可以在上面先用,后面再写,因为预编译(可以解决onload)
<script>
var myconsole={
mylog:()=>{console.log("111")}
}
function fn() {
console.log("222")
}
</script>
2.方法二:元素属性绑定方式
ele.onxxx=function(event){}
句柄式写法,基本等同于写在HTML行间上
兼容性很好,但是一个元素的同一个时间上只能绑定一个处理程序。
解决方法就是:在函数内再执行其它的函数,就相当于绑定了多个处理程序
var btn2 = document.getElementById('btnId2'); //1.获取事件源:按钮
btn2.onclick = function () { //2.绑定事件,即将事件类型(鼠标点击(onclick))绑定到事件源上。
alert('弹窗'); //3.编写事件处理程序:弹出一个警告框。
fm() //相当于绑定多个处理程序
}
3.方法三:用监听事件绑定:
也称为:同元素多处理程序 (绑定方式1)
IE9以下不兼容,可以为一个事件绑定多个处理程序,这个方法行内的事件不会被覆盖
同一个元素同一个事件可以注册多个监听器, 按注册顺序依次执行。(IE8及其以下的按注册顺序相反顺序执行)
obj.addEventListener(type,fn,false)
addEventListener:是异步非阻塞函数 (异步非阻塞函数:setTimeout、setInterval)
type:事件类型。比如点击事件、鼠标事件(类型自己不能设计,浏览器自己写,这就是达到某种状态)
fn:监听程序,回调函数(点击的时候函数才调用)
false:是否捕获阶段触发,跟冒泡没关系 (笔试陷阱题)
1.元素对象.addEventListener('事件名(不带on)', 匿名函数); //IE9及其以上才支持 这个常写
2.元素对象.attacheEvent('事件名(带on)', 匿名函数); //IE8及其以下才支持
var btn4 = document.getElementById('btnId4');
btn4.addEventListener('click', function () { //注意这里的事件类型(鼠标点击('click'))。
alert('hai');
})
4. 方法四:IE下使用attachEvent/detachEvent函数进行事件绑定
也称为:同元素多处理程序 (绑定方式2) 它没有第三个参数
IE专有( ie11例外),一个事件同样可以绑定多个处理程序
attachEvent/detachEvent兼容性不好,IE6~IE11都支持该函数,但是FF和Chrome浏览器都不支持该方法。而且attachEvent/detachEvent不是W3C标准的做法,所以不推荐使用。
obj.attachEvent('on'+type,fn);
<meta http-equiv="X-UA-Compatible" content="IE=10" />,解决 IE11向后兼容 IE10的问题
box.attchEvent("click", function () {
console.log(6)
})
//判断浏览器可以用哪一个运行
box.adde = box.addEventListener || box.attchEvent
box.adde("click", function () {
console.log(666663)
})
5.多元素同事件同处理程序绑定方式==>代理模式
box.οnclick=function(e) { e.target } //父元素绑定事件 通过事件对象来区分用户触发的事件属于哪一个具体的对象
三、事件解绑
1、box.onclick = false / '' / null; 行内和属性解绑
//行内解绑
<div id="xiake" onclick="console.log('下课1')">
下课
</div>
<script>
xiake.onclick = function () {
xiake.onclick = null;
}
//属性解绑
var box = document.getElementById('box');
box.onclick = function () {
box.onclick = null;
}
</script>
2、box.removeEventListener(type,fn,false); 解绑监听事件
//移除对应的元素的对应的监听程序
function fn1() {
console.log("真下课1")
}
function fn2() {
console.log("真下课2")
}
box.addEventListener("click", fn1)
box.addEventListener("click", fn2)
box.removeEventListener("click", fn1)
3、box.detachEvent("on"+type,fn);
ps:2,3若绑定的是匿名函数,或者没有名字的箭头函数,则永远无法解除
四、事件中的this和事件对象
1.行内:
<button type="button" onclick="fn(this)">xxx</button>
<script type="text/javascript">
function fn (e) {
console.log(e,this)//btn和window
}
</script>
//行内绑定时 行内的环境对象是btn 函数的调用者是window 无法获取事件对象
2.元素属性:
this指向的是dom元素本身 事件对象在参数中
<button id="btn2">btn2</button>
<script>
btn2.onclick=function fn (e) {
console.log(this,e) //button,事件对象
console.log(window.event) //打印事件
}
</script>
3.addEventListener:
this指向的是dom元素本身 事件对象在参数中
btn2.addEventListener("click",function(e){
console.log(e,this) //事件对象 button
})
obj = {
say: function () {
btn2.addEventListener("click", (e) => {
console.log(e, this) //事件对象 {say: ƒ}
})
}
}
obj.say()
4.attachEvent:
this指向 window 事件对象在参数中
兼容性:判定是行内绑定还是元素绑定,然后打印事件对象
<button id="btn2" onclick="fn(100)">btn2</button> <!--行内绑定写法--> <!-- <button id="btn2">btn2</button> --> <!--元素绑定写法--> <script> btn2.onclick=function fn (e) { //e.constructor==PointerEvent&&e表示:e的对象是不是事件对象,如果是的话那表达式结果为true&&e,最后结果为e。不是的话就为flase||e,结果为false,然后就等于window.event e=(e.constructor==PointerEvent&&e)||window.event //前面就是行内绑定打印,后面就是属性绑定方式 console.log(e) //打印事件对象 } </script>
五、事件类型
1、鼠标事件
1、click、 mousedown、mousemove、mouseup、dblclick、 contextmenu、mouseover、mouseout、mouseenter(html5标准)、mouseleave(html5标准)
a) mousedown-->mouseup-->click
b) mousedown:鼠标按下一次就只触发一次;
c) mousemove与 mousedown无关,相互独立;
d) 补充:移动端没有 mousedown事件,对应的是 touchstart--touchmove--touchend
e) dblclick:鼠标第一次按下和第二次松开时,鼠标指针在被选元素区域内部,并且时间间隔不能太长
f)mouseup : 在被选元素区域内部 松开就触发一次 (随便在哪按)
g) mouseover : 鼠标进去 被选元素区域内部 就会触发 (给父元素设置的,子元素也有此效果)
h) mouseout:鼠标从被选元素区域内部出去 就会触发
i) mouseleave : 鼠标从被选元素区域内部出去 就会触发
j)mouseenter : 鼠标进去 被选元素区域内部 就会触发
上面四个笔试/面试经常考,要研究父元素 子元素之间的切换的触发
k) onwheel : 鼠标滚轴滚动时,鼠标指针在被选元素内部
m) mousemove :
2、DOM3标准规定:
click事件只能监听左键,mousedown和 mouseup来判断鼠标键,event.button来区分鼠标的按键,0/1/2
2、键盘事件
1、keydown、keyup、keypress
a) keydown-->keypress-->keyup
b) keydown 在按键按下之后会一直不断被触发。每按一次就会触发一次。比如输入hai,就会打印三次
c)keyup :在按键按下之后松开的时候就触发
d)keypress:按下的时候一直触发
2、keydown和 keypress的区别
a) keydown可以响应任意按键(除了Fn键)
keypress只可以响应字符类键盘按键(event.charCode)
b)keypress返回 ASCII码,可以转换成相应字符(String.fromCharCode(event.charCode),区分大小写)
keydown常用于绑定操作类事件处理,keypress常用于绑定字符类事件处理
3、输入框操作事件
1、input、focus、blur、change
a) input监听 :input框在聚焦状态下的文本变化,在框中每输入就会触发。例:百度搜索
它和 keydown不一样, keydown是监听键盘,一般的标签都可以绑。input是监听value,可以语音输入,它用的更多,只给input绑
b) change监听 :input框在失焦后的文本变化,并且输入框的value值发生变化(与前一次失焦状态的文本对比变化),就会触发。例如:表单验证,常用
c) focus 和 blur 只在聚焦和失焦的一刻触发一次 也可用于表单验证
box2.focus() //这是调函数
box2.addEventListener("focus",function(){
console.log("输入框获取焦时触发")
})
4、其他事件
1、scroll 属于元素事件
window.οnscrοll=func
常用于绑定在window对象上,滚动鼠标时触发,触发的次数与事件有关
2、load 加载事件
load:等待网页资源下载完毕再执行
img.onload 图片节点加载完毕不会调用 要资源加载完毕就会调用
window.onload:等待页面所有资源下载完成(浏览器加载完毕:5大BOM的功能加载完毕)才执行,包括图片资源的下载,所以它是最慢的
网页加载顺序:url-->下载页面-->domTree,cssTree并行-->渲染树renderTree-->绘制页面-->继续下载图片资源,下载完毕再放到页面上去onload domTree:domTree的形成,是先把元素翻译成的节点对象挂到 domTree上去,再把属性 img_src放到渲染树上去
每年都考的面试题:用户从地址栏输入网址按下回车到页面展示出来 整个过程发生了什么?
答案:前端=>网络=>后端=>网络=>前端 这4步都得分析
六、事件对象
1、事件对象
事件对象上存储着事件发生时的相关信息(例如:event.which)
a) 事件处理函数形参ev(event),W3C制定的标准,IE9以下不行 b) 全局对象 window.event用于IE9以下 // 兼容性写法 var event= ev|| window.event
2、事件对象携带的信息
事件触发时,hanler函数内部会传入数据==>触发时的信息
事件源对象:
event.target 火狐只有这个 event.srcElement IE6/78只有这个 这两个chrome都有 兼容性写法 var ele=event.target|| event.srcElement
鼠标事件触发时:
(事件对象与盒子模型的区别:事件对象是鼠标/点击的距离,而盒子模型是元素)
altKey 鼠标事件发生时,是否按下alt键,返回一个布尔 (用于网页游戏的设计) ctrlKey 鼠标事件发生时,是否按下ctrl键,返回一个布尔 (用于网页游戏的设计) metaKey 鼠标事件发生时,是否按下windows/commond键,返回一个布尔 shiftKey 鼠标事件发生时,是否按下shift键,返回一个布尔 pageX 鼠标点击的 X 坐标;(包含body隐藏的) pageY 鼠标点击的 Y 坐标;(包含body隐藏的) 滚动页面,上面的距离也算 clientX clientY返回鼠标位置相对于浏览器窗口左上角的坐标,单位为像素(不包括body隐藏的) screenX screenY返回鼠标位置相对于屏幕左上角的坐标,单位为像素 movementX,movementY返回一个位移值,单位为像素,表示当前位置与上一个mousemove事件之间的距离 (有负有正) offsetX/offsetY 相对于元素自己的x/y 跟它是否是定位的元素无关 (偏移量)
input元素的事件对象:
1、input中的oninput事件
<input type="text" name="" id="btn2"> <script> //输入框中输入的是12,所以打印了两次 //打印的data是当前触发的内容,比如第二个里的data就是2,而不是输入框中的内容 //要获取输入框中的内容:通过获取当前节点对象的value值,有三种方法 btn2.oninput=function(e){ console.log(btn2.value,this.value,e.target.value) //获取输入框中内容的三种方法 } //每次触发打印的内容还有:type(事件类型)、target、path(事件链,不是节点链)。 //比如这一个案例:type:input;target:input#btn2;path: (5) [input#btn2, body, html, document, Window] </script>
2、input中的键盘事件
<input type="text" name="" id="box2"> <script> box2.onkeydown=function(e){ console.log(e,e.keyCode,box2.value,this.value,e.target.value) } //打印后:key:"你输入的文字";keyCode:"键盘上的键码";cyrlKey:true;等等 </script>
当输入上下左右键的时候,keyCode对应的值:37左 38上 39右 40下 13enter (背)
charCode/keyCode 键码值 key 键码