JS 进阶(7) DOM事件:主流浏览器dom2级事件、IE6~IE8dom2级事件、事件冒泡、事件委托、事件类型

本文详细介绍了DOM2级事件,包括事件定义、绑定与移除,特别关注了IE6-IE8的事件处理方式。此外,还讨论了事件冒泡、事件捕获、事件委托的概念及其应用,以及各种事件类型的使用场景,如load、unload、click等,最后提及了移动端事件和DOM结构变化事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是事件?

事件是可以被js侦测到的行为,当用户与web页面进行交互时,解释器就会创建响应的event对象来描述事件。

常见的事件有哪些?

  • 点击页面上某个元素
  • 鼠标经过特定的元素
  • 按下键盘上某个按键
  • 滚动窗口或改变窗口大小
  • 页面元素加载完成或失败

一、主流浏览器 dom2级事件定义(包括IE9+)

1.1 事件定义三种方式

这里重点讲dom2级事件

  1. 在html元素中定义事件
<button onclick="alert('hello')">按钮</button>
缺点:html中写js代码。强耦合,不利于服用代码,违反了内容与行为相分离的原则。
  1. dom0级事件
    事件对象的属性添加绑定事件。
	document.getElementById('btn').onclick = function(){}
	
	document.body.onload = init;
	function init(){ ....}
优点:兼容所有浏览器包括IE6~IE8,可以进行事件模拟.
缺点:同一个事件只能绑定一个监听函数
  1. dom2级事件:addEventListener
btn.addEventListener('click',function(){},false);	主流浏览器
btn.attachEvent('onclick',function(){})				IE
优点:高级事件处理方法,一个事件可以绑定多个函数。
缺点:浏览器的兼容性。


1.2 dom2级事件

dom2级事件的优点:

  • 允许事件对象绑定多个同种事件
  • 事件捕获
  • 事件冒泡

1.2.1 绑定事件addEventListener()

功能:添加的事件函数
语法:ele.addEventListener(event, functiion, useCapture)
参数说明:

  • event 必选。字符串,要移除的事件名称。
  • function 必选,指定要移除的函数。
  • useCapture 可选,布尔值,默认为false(事件冒泡),true(事件捕获)

addEventListener()可以绑定多个同类型事件。

var btn = document.getElementById('btn');
btn.addEventListener('click',function(){alert(1)},false);
btn.addEventListener('click',function(){alert(2)},false);

1.2.2 移除事件removeEventListener()

功能:移除addEventListener()方法添加的事件函数
语法:ele.removeEventListener(event, functiion, useCapture)
参数说明:

  • event 必选。字符串,要移除的事件名称。
  • function 必选,指定要移除的函数。
  • useCapture 可选,布尔值,默认为false,指定移除事件句柄的阶段。

移除事件的坑
如果想要用removeEventListener()进行事件解绑,那就在绑定事件的时候不能使用匿名函数。

var btn = document.getElementById('btn');
btn.addEventListener('click',function(){alert(1)},false);
btn.removeEventListener('click',function(){alert(1)},false);

上面的解绑事件看似解绑的是同一个除了函数,但是这两个匿名函数不是同一个,只有使用functionvar声明的函数,才能拿到函数体的地址,指向同一个函数。

var fn = function(){alert(1)};
btn.addEventListener('click',fn,false);
btn.removeEventListener('click',fn,false);


二、IE6~IE8 dom2级事件定义

这里的方法只有 IE6~IE8支持。
只有事件冒泡,没有事件捕获。

2.1 添加事件attachEvent()

属于dom2级事件,也是可以绑定多个事件处理函数。

语法

ele.attachEvent(event,function);

参数说明:

  • event 必须,指定事件名,必须添加on前缀。
  • function 必须,指定事件触发时的执行函数。
  • 没有第三个参数,因为ie6~ie8不支持事件捕获。

2.2 移除事件detachEvent()

移除attachEvent()方法添加的监听函数。

语法

ele.detachEvent(event, function);

参数说明:

  • event 必须,指定事件名,必须添加on前缀。
  • function 必须,指定事件触发时的执行函数。
  • 没有第三个参数,因为ie6~ie8不支持事件捕获。

2.3 IE8中this的指向问题

在IE8及更早版本浏览器 中dom2级事件中的this指向的不是当前对象,而是window

	var btn = document.getElementById('btn');
	var test = function(){
		alert(this === window);		true
	}
	
	EventUtil.addHandler(btn,'click',test);

三、跨浏览器事件处理

封装一套兼容低版本浏览器和主流浏览器的事件添加和移除的代码。

EventUtil这个对象可以直接写在单独的js中引用即可

var EventUtil = {
	addHandler: function(element, type, handler){
		if(element.addEventListener){	//主流浏览器
			element.addEventListener(type, handler, false);
		}else if(element.attachEvent){	//ie8以下
			element.attachEvent('on'+type, handler);
		}else{
			element['on'+type] = null;
		}
	},
	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;
		}
	}
};


var btn = document.getElementById('btn');
var test = function(){
	alert(1);
}
EventUtil.addHandler(btn,'click',test);
EventUtil.removeHandler(btn,'click',test);

四、事件冒泡与事件捕获

在这里插入图片描述

  • 事件冒泡(大多数情况都是使用事件冒泡)
    事件对象沿dom树向上传播,目标触发运行事件监听函数。
主流浏览器:addEventListener(type, function, false) 或者 addEventListener(type, function);
IE6~IE8:attachEvent(type, function);
  • 事件捕获(几乎不用)
    事件对象沿dom树向下传播,目标触发运行事件监听函数。
addEventListener(type, function, true);

4.1 事件冒泡

直系亲属树结构中,点击某个元素,由于冒泡作用,亲属树上的元素凡是添加了事件的,都会被触发。

	<div id="parent">
		<div id="child">点击儿子</div>
	</div>
	<script type="text/javascript">
		document.getElementById('parent').addEventListener('click',function(){
			alert('parent'+this);
		},false);
		document.getElementById('child').addEventListener('click',function(){
			alert('child'+this);
		},false);
	</script>

点击儿子,会先弹出child,再弹出parent。

4.2 事件捕获

	<div id="parent">
		<div id="child">点击儿子</div>
	</div>
	<script type="text/javascript">
		document.getElementById('parent').addEventListener('click',function(){
			alert('parent'+this);
		},true);
		document.getElementById('child').addEventListener('click',function(){
			alert('child'+this);
		},true);
	</script>

会先弹出parent,再弹出child


五、事件委托

dom2级事件和dom0级事件都是可以利用冒泡机制进行事件委托的。

事件委托就是利用冒泡的原理,把事件加到父级上,触发执行。
使用事件委托的可以提高性能。

<ul id="ul">
	<li>item1</li>
	<li>item2</li>
	<li>item3</li>
	<li>item4</li>
	<li>item4</li>
</ul>

<li>一个个绑定点击事件非常消耗性能和内存,并且大多数下<li>的个数是不确定的。
所有我们可以将事件处理函数绑定在其父亲<ul>上,利用event对象就可以得到事件触发元素对象

	document.getElementById('ul').addEventListener('click',function(event){
		console.log(event.target);
	},false);


5.1 event对象

addEventListener()中event对象常用属性和方法:

  • type 事件类型
  • target 事件源,当前触发事件的元素
  • currentTarget 绑定事件的元素
  • preventDefault() 阻止事件默认行为
  • stopPropagation() 阻止事件冒泡或捕获
  • clientY 浏览器可视区域顶部底边到鼠标的位置(clientX同理)
  • pageY 浏览器可视区域顶部底边到鼠标的位置,计算滚动轴的距离。(pageX同理)
  • screenY 屏幕的顶端到鼠标的位置(screenX同理)

IE8及以下attachEvent()中event对象常用属性和方法:

  • type 事件类型
  • srcElement 同target
  • returnValue = false 阻止默认行为同preventDefault()
  • cancelBubble = true 取消事件冒泡同stopPropagation()

5.1.1 type 事件类型

可以用来统一事件处理的方法

var eventFun = function(event){
	if(event.type == 'click'){
		...
	}else if(event.type == 'mouseout'){
		...
	}
}

btn.addEventListener('click',eventFun );
btn.addEventListener('mouseout',eventFun );

5.1.2 target 事件源对象

点击谁谁就是target,事件源。


5.1.3 currentTarget 处理事件的绑定对象

事件绑定在谁身上,就指向谁。


5.1.4 preventDefault() 阻止默认行为

阻止跳转
<a href="https://www.baidu.com" id="a">点击跳转</a>
<script>
	var a = document.getElementById("a");
	a.addEventListener('click',function(){
		event.preventDefault();
	},false);
</script>

5.1.5 stopPropagation() 阻止事件的冒泡或捕获

	<div id="parent">
		<div id="child">点击儿子</div>
	</div>
	<script type="text/javascript">
		document.getElementById('parent').addEventListener('click',function(){
			alert('parent'+this);
		},false);
		document.getElementById('child').addEventListener('click',function(event){
			alert('child'+this);
			event.stopPropagation();
		},false);
	</script>

点击儿子,只会弹出child。


5.2 Event对象跨浏览器写法

	var EventUtil = {
		addHandler: function(element, type, handler){
			if(element.addEventListener){
				element.addEventListener(type, handler, false);
			}else if(element.attachEvent){
				element.attachEvent('on'+type, handler);
			}else{
				element['on'+type] = null;
			}
		},
		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;
			}
		},

		//event跨浏览器
		getTarget: function(event){
			return event.target || event.srcElement;
		},
		preventDefault: function(event){
			if(event.preventDefault){
				event.preventDefault();
			}else{
				event.returnValue = false;
			}
		},
		stopPropagation: function(event){
			if(event.stopPropagation){
				event.stopPropagation();
			}else{
				event.cancelBubble = true;
			}
		}
	};

	使用案例
	var btn = document.getElementById('btn');
	var test = function(event){
		EventUtil.stopPropagation(event);
	}
	EventUtil.addHandler(btn,'click',test);


六、事件类型

比较实用的事件类型

  • ul事件
  1. load 页面或资源(img、js、css等)加载完毕以后触发
  2. unload 用户从一个页面切换到另一个页面触发
  3. resize 窗口大小发生变化时触发(重复执行,损耗性能)
  4. scroll 页面上下滚动的时候触发
  • 焦点事件
  1. blur 元素失去焦点时触发
  2. focus 元素获得焦点时触发
  3. focusin 同focus一样,但是支持冒泡
  4. focusout 同blur一样,失去焦点时触发(支持低版本IE)
  • 鼠标事件
  1. click 点击时触发 (click = mousedown + mouseup)
  2. dblclick 双击时触发 (PS:jquery不支持双击事件)
  3. mousedown 鼠标按下
  4. mouseup 鼠标松开
  5. mousemove 鼠标在目标元素上移动时触发(重复执行,损耗性能)
  6. mouseover 鼠标进入目标元素(或者目标元素的子元素)
  7. mouseout 鼠标离开目标元素(或者目标元素的子元素)
  8. mouseenter 鼠标进入目标元素 (只能进入目标元素才触发,进入目标元素的子元素不会触发)
  9. mouseleave 鼠标离开目标元素(只能离开目标元素才触发,离开目标元素的子元素不会触)
  • 键盘事件
  1. keydown 键盘上任意键按下时触发(支持keyCode)
event.keyCode	可以获得键码
  1. keyup 释放任意键时触发(支持keyCode)
  2. keypress 按下字符键触发(回车,f1,f2这些不支持,keyCode不稳定)
event.charCode	获得ASCII
  1. textInput 在文本框中输入每一个字符时触发
event.data	获得输入的每一个字符
  • dom结构事件
  1. DOMNodeRemoved 删除 目标元素中 的任意元素时触发
  2. DOMNodeIInserted 目标元素中 被添加任意元素触发
  3. DOMSubtreeModified 目标元素中 的dom结构发生任何变化(添加、删除等等)触发
  4. DOMNodeRemovedFromDocument 目标元素被移除前触发
  5. DOMNodeInsertedIntoDocument 被添加之前触发
  • HTML5新增事件
  1. DOMContentLoaded dom树加载完成之后就触发,比load快很多。

  2. hashchange 只能给window添加,网页url#后面的值变化时触发

  3. 移动端事件

  • touchstart:手指触摸时触发
  • touchend:手指从屏幕上移开时触发
  • touchmove:手指在屏幕上滑动时触发
  • touchcancel 当系统停止跟踪触摸时触发

6.1 onload

当页面完全加载完毕触发

	EventUtil.addHandler(window, 'load', function(event){...});

当图片加载完后触发

在图片非常大的时候

	var image = document.createElement('img');
	image.src = '../1.png';
	EventUtil.addHandler(image, 'load', function(event){
		....
	});

图片预加载

	var image = new Image();	将图片缓存到内存中
	image.src = '../1.png';
	EventUtil.addHandler(image, 'load', function(event){
		....
	});

js动态加载完毕

	EventUtil.addHandler(window, 'load', function(event){
		var script = document.createElement('script');
		script.src = 'XXX.js';
		Event.addHandler(script, 'load', function(event){
			....
		});
		document.body.appendChild(script);
	});

css动态加载完毕

	EventUtil.addHandler(window, 'load', function(event){
		var link = document.createElement('link');
		link.type = 'text/css';
		link.rel = ''stylesheet;
		link.href = 'xxxx.css';
		EventUtill.addHandler(link, 'load', function(event){
			...
		});
		document.getElementsByTagName('head')[0].appendChild(link);
	});

6.21 DOMNodeRemoved

document中任意元素删除时触发

EventUtil.addHandler(document, 'DOMNodeRemoved', function(event){
	...
});

指定元素中的元素被删除时触发

var ul = document.getElementsTagName('ul')[0];
EventUtil.addHandler(ul, 'DOMNodeRemoved', function(event){
	...
});

6.27 hashchange

	EventUtil.addHandler(window, 'hashchange', function(event){
		console.log(event.oldURL);
		console.log(event.newURL);
	});

6.28 移动端事件

移动端常用事件

  • touchstart:手指触摸时触发

  • touchend:手指从屏幕上移开时触发

  • touchmove:手指在屏幕上滑动时触发

  • touchcancel 当系统停止跟踪触摸时触发

移动端常用事件对象的属性

  • event.touches 获取当前触摸屏幕的触摸点数组(不管触摸点是不是在目标元素内)
  • event.changedTouches 数组中只包含引起事件的触摸点信息
  • event.targetTouches 只包含放在元素上的触摸信息

在移动端的时候,手机屏幕上可能有多个触摸点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值