基础事件

126 阅读10分钟

基础事件

事件句柄

属性此事件发生在何时
onclick用户左键点击某个对象时调用的事件句柄
ondblclick用户双击某个对象时调用的事件句柄
oncontextmenu用户鼠标右键点击某个对象时调用的事件句柄
onmousedown鼠标按钮按下
onmouseup鼠标按钮抬起
onmouseover鼠标移到某元素上(移入子集盒子也会触发)
onmouseout鼠标移出某元素(移入子集盒子也会触发)
onmouseenter鼠标移到某元素上(不支持冒泡 )子元素不影响
onmouseleave鼠标移出某元素(不支持冒泡 )子元素不影响
onmousemove鼠标移动
键盘句柄
onkeyup键盘抬起
onkeydown键盘按下事件
onkeypress键盘按下抬起 (中文状态下不响应)
oninputinput内容有输入的时候触发 (响应输入法)
input句柄
onfocus**获得元素焦点焦点
onblur失去焦点
onchange文本内容被改变 并且失去了焦点
oninput获得了焦点,正在输入
加载三件套
onabort图片的加载被中断
onerror在加载文档或图像时发生错误(网络状态 类似断网了突然)
onload加载完成
onreset重置按钮被点击
onresize窗口或框架被重新调整大小
onselect文本被选中
onsubmit确认按钮被点击
onunload用户退出页面
onscroll滚动触发
var oBtn = document.querySelector('#btn');
oBtn.onclick = function(e){
	console.log(e)
	this.value = '不要点我';
    //回调函数中的this指向 触发事件的对象
    //this=>oBtn 
}
//事件回调函数会回调形参 e Event对象

事件:触发-响应机制

Event接口表示在DOM中发生的任何事件,一些是用户生成的(例如鼠标或键盘事件),而其他由API生成

事件三要素

  • 事件源:触发(被)事件的元素
  • 事件类型:事件的触发方式(例如鼠标点击或键盘点击)
  • 事件处理程序:事件触发后要执行的代码(函数形式)
元素.事件=function(){
    处理程序
}

事件阶段

事件有三个阶段:

event.eventPhase属性可以查看事件触发时所处的阶段 :

  1. 捕获阶段

  2. 当前目标阶段

  3. 冒泡阶段

    1、事件捕获

    捕获型事件(event capturing):事件从最不精确的对象(document 对象)开始触发,然后到最精确(也可以在 窗口级别捕获事件,不过必须由开发人员特别指定)

    2、事件冒泡

    冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。

    绑定的事件默认的执行时间是在冒泡阶段执行,而非在捕获阶段(重要)。这也是为什么当父类和子类都绑定了某个事 件,会先调用子类绑定的事件,后调用父类的事件 事件对象的属性和方法
    

事件对象的属性和方法

event对象属性

属性描述
keyCode表示非字符案件的unicode(已经)
key**新方法 获取的是具体的值 比如abcd
altKey返回当事件被触发时,"ALT" 是否被按下。
shiftKey返回当事件被触发时,"SHIFT" 键是否被按下。
ctrlKey返回当事件被触发时,"CTRL" 键是否被按下。
metaKey返回当事件被触发时,"meta" 键是否被按下。
target **返回触发此事件的元素(事件的目标节点)。
eventPhase返回事件传播的当前阶段。
type **返回当前 Event 对象表示的事件的名称比如:click
clientX以浏览器左上顶角为原点,定位 x 轴坐标
clientY以浏览器左上顶角为原点,定位y轴坐标
offsetX以当前事件的目标对象content左上角为原点,定位x轴坐标
offsetY以当前事件的目标对象content左上角为原点,定位y轴坐标
pageX以Document 对象(即文本窗口)左上角为原点,定位x轴坐标
pageY以Document 对象(即文本窗口)左上角为原点,定位y轴坐标

当触发一个事件的时候,对该事件的一些描述

比如:1.鼠标点击时的位置

2.触发键盘的时候按下的哪个键

每一个事件都会有一个对象来描述这信息,我们就把这个对象叫事件对象

浏览器会给我们一个黑盒子,叫做window.event 就是对事件信息的所有描述

//语法:
元素.onclick = function(){
     consolo.log(window.event.x轴坐标)
     consolo.log(window.event.x轴坐标)
   }
   缺点:存在兼容性问题 低版本ie和谷歌里边不好使

解决方法:

事件函数的第一个形参,默认为事件对象

//e是一个形参 默认为了事件对象 调用事件对象中的各种方法
oDiv.onclick = function(e){
      console.log(e.offsetX)
}

鼠标Event位置

事件触发的时候 鼠标位置

offset

1.相对于事件源offset

鼠标距离点击对象边框的距离(不包括边框距离)

page

2.相对于页面page

pageX pageY

相对于页面 会计算滚动给条的距离

client

3.相对于浏览窗口clientX

只看浏览器窗口距离

var oDiv  = document.querySelector('div')

    //1.相对于点击对象距离 offset
    oDiv.onclick = function(e){
      //offset 相对于点击对象 距离点对象边框的距离(不包括边框)
      console.log(e.offsetX)
      console.log(e.offsetY)
      
      //相对于页面 会计算滚动条的距离
      console.log(e.pageX)
      console.log(e.pageY)

      //相对浏览器窗口 只看窗口距离
      console.log(e.clientX)
      console.log(e.clientY)

    }

鼠标event.png

事件方法

阻止事件传递(阻止冒泡)

所有的事件类型都会经历事件捕获但是只有部分事件会经历事件冒泡阶段,例如submit事件就不会被冒泡。

事件的传播是可以阻止的:
w3c规范下,使用stopPropagation()方法
在IE版本下设置eve.cancelBubble = true; 废弃
在捕获的过程中stopPropagation();后,后面的冒泡过程就不会发生了。

var oLink = document.querySelector('a');
oLink.onclick = function(e){
	e.stopPropagation();
}

事件解绑

事件绑定之后 如果需要解绑 可以销毁

常用 弹窗点击 弹窗关闭后 弹窗内的绑定需要解绑 以防有人改代码显示后 继续点击

var oBtn = document.querySelector('#btn');
var oClean = document.querySelector('#clean');
oBtn.onclick = function(){
	console.log('btn成功绑定点击事件');
}
oClean.onclick = function(){
	oBtn.onclick = null;
	console.log('btn已解绑点击事件');
}

事件监听**

www.bilibili.com/video/BV1AU…

默认情况下:监听addEventListener、detachEvent解绑 必须是函数名 匿名函数的不可以解绑

事件绑定方法 on 和监听

DOM.on方法 = 匿名函数 或 函数名

addEventListener(事件类型,事件处理程序( 匿名函数 或 函数名),事件触发阶段(冒泡或捕获))

//元素.addEventListener('事件类型',事件处理程序,事件触发阶段)
window.addEventListener("resize", function(){
	console.log(window.innerWidth,window.innerHeight); 	// document.documentElement.width
},false);

注意:
1. addEventListener用于标准浏览器 attachEvent用于老版本IE浏览器
2. addEventListener参数依次为 事件名称(不加on) 事件触发函数 事件触发阶段(true:捕获,false:冒泡)
3. addEventListener 回调函数内部this指向 绑定对象

解除监听

oWrap.removeEventListener("click",touch,false);
oWrap.detachEvent("onclick",touch);
注意:用什么方式绑定事件,就应该用对应的方式解绑事件
1.
对象.on事件名字=事件处理函数--->绑定事件
对象.on事件名字=null;
2.
对象.addEventListener("没有on的事件类型",命名函数,false);---绑定事件
对象.removeEventListener("没有on的事件类型",函数名字,false);
3.
对象.attachEvent("on事件类型",命名函数);---绑定事件
对象.detachEvent("on事件类型",函数名字);

事件监听与on绑定区别 (**)

on事件会被后面的on的事件覆盖, addEventListener 则不会覆盖;

addEventListener可以指定事件回调触发时机 (捕获 or 冒泡) on事件只有 冒泡时刻触发

addEventListener本质是函数定义与具体调用事件的解耦,实现了同一事件可以调用多个函数,同一函数 可以被多个事件调用,推荐使用

兼容写法

//为任意一个元素绑定事件:元素,事件类型,事件处理函数
function addEventListener(element,type,fn) {
	if(element.addEventListener){
	//支持
		element.addEventListener(type,fn,false);
	}else if(element.attachEvent){
		element.attachEvent("on"+type,fn);
	}else{
		element["on"+type]=fn;
	}
}

//为任意的一个元素解绑某个事件:元素,事件类型,事件处理函数
function removeEventListener(element,type,fn) {
	if(element.removeEventListener){
		element.removeEventListener(type,fn,false);
	}else if(element.detachEvent){
		element.detachEvent("on"+type,fn);
	}else{
		element["on"+type]=null;
	}
}

方法区别

1.方法名不一样
2.参数个数不一样addEventListener三个参数,attachEvent两个参数
3.addEventListener 谷歌,火狐,IE11支持,IE8不支持
attachEvent 谷歌火狐不支持,IE11不支持,IE8支持
4.this不同,addEventListener 中的this是当前绑定事件的对象
attachEvent中的this是window
5.addEventListener中事件的类型(事件的名字)没有on
attachEvent中的事件的类型(事件的名字)有on

匿名解绑监听(封装方法)

自定义一个方法实现 匿名函数的解绑

var btn = document.getElementById('btn');
var cancel = document.getElementById('cancel');
var listenBySL = function(element, type, handler, capture){
	capture = capture || false;
	if(element.addEventListener){
		// W3C内核
		element.addEventListener(type, handler, capture);
	}else{
	// IE内核
		element.attachEvent('on'+type, handler);
	}
	return {
		"remove":function(){
			if(element.removeEventListener){
				// W3C内核
				element.removeEventListener(type, handler,capture);
			}else{
				// IE内核
				element.detachEvent('on'+type, handler);
			}
		}
	}
}
// 添加监听 赋值是为了得到返回值 一个解绑对象 方便解绑
var addAlert = listenBySL(btn,'click',function(){
	alert(123);
});
listenBySL(cancel,'click',function(){
	// 移除监听
	addAlert.remove();
    //函数名调用 remove对象方法
	alert('移除成功');
});
addAlert.remove()

事件传播

概念

当元素触发一个事件的时候,这个元素的父级节点也会触发系统的事件,父元素的父元素也会触发依次传播

  1. 点击了子盒子,会触发了子盒子的点击事件
  2. 也是点在了父盒上,也会触发父盒子的点击事件
  3. 也是点在了body上,也会触发body的点击事件
  4. 也是点在了html上,也会触发html的点击事件
  5. 也是点在了document上,也会触发document的点击事件
  6. 也是点在了window上,也会触发window的点击事件
  7. 页面上任何一个元素的触发事件,都会一层一层的最终导致window的相同事件触发

注意:

1.只会传播同类事件,比如点击事件 ...

2.事件传播 是依次向上传播输出

3.元素的内部元素 不管有没有相同触发事件 内部元素都会触发父盒子的点击事件

​ (除了可以隔绝事件传播的事件比如:onmouseenter onmouseleave)

4.如果传播中 有的元素没有这个点击事件 跳过 接着像上传

自我理解

​ html是层级关系 是叠起来的 子的在父的上面

​ 就是 胸口碎大石 人 大石头 小石头 手

​ 打人 人疼, 打小石头 人疼,打手 手 人 疼

​ 石头不疼 为什么 因为石头没有感觉(就是没有相同的触发事件)

*/

冒泡与捕获与目标(面试)

先捕获再冒泡 但冒泡阶段才执行事件

举例 点击事件

目标

​ 你点击的元素 就是目标

冒泡 on和事件监听

​ 就是从目标的事件从下向上的执行 一直到window

​ 普通方法只有冒泡

​ 事件绑定方法的第三个参数可以设置冒泡捕获 true就是捕获 不写默认false冒泡

捕获 (只能用事件鉴定)

​ 就是从window的事件从上向下的执行 一直到目标函数

冒泡和捕获点击的都是目标元素 只不过一个从目标->window 一个是window->目标

事件委托

当需要对多个子元素进行循环事件绑定的时候,可以将事件委托与他们的共同父级,通过event对象属性来进 行筛选和操作,节省开销

概念

​ 就是要把自己做的事 委托给别人 帮我完成

​ 理论就是冒泡排序

​ 点击子元素的时候,不管子元素有没有点击事件

补充target

​ 这个属性是事件对象的属性,表示你点击的目标

​ target兼容性有问题 在ie浏览器内 需要使用srcElement

var oul = document.querySelectoer('ul')
oul.onclick = function(e){
	if(e.target.nodeName === 'LI'){
       console.log('woshili')
  	}
}

阻止默认事件行为(了解)

有三种方法

在a标签href中写javascript

e.preventDefault()

return false

很多标签拥有默认的事件行为 比如a标签 点击会执行跳转页面行为 , 我们可以通过代码阻止这些行为

var oLink = document.querySelector('a');
oLink.onclick = function(e){
e.preventDefault();
//preventDefault它是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为
}
oLink.onclick = function(e){
//代码
return false; //回调函数最后返回false可以阻止默认行为
}