JavaScript(事件的详细解答)

事件概念

事件冒泡

事件冒泡:事件的向上传递,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发,在开发中大部分情况,冒泡都是有用的,如果不希望发生事件冒泡,可以通过事件对象来取消冒泡。[运行后,点击span,box1和body的点击事件都会被触发,称为事件冒泡]。
event.cancelBubble=true;

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>显示鼠标坐标</title>
		<style type="text/css">
		#box1{
			width:  100px;
			height: 100px;
			background-color:greenyellow;
		}
		#s1{
			background-color: crimson;
		}
		</style>
	</head>
	<body>
		<div id="box1">
			<span id="s1">我是span</span>
		</div>	
		
		<script type="text/javascript">
			/*事件冒泡:事件的向上传递,当后代元素上的事件被触发时
			 其祖先元素的相同事件也会被触发
			 在开发中大部分情况,冒泡都是有用的,如果不希望发生事件冒泡
			 可以通过事件对象来取消冒泡*/
			
			
			//为s1绑定一个单击响应函数
			var s1=document.getElementById("s1");
			s1.onclick=function(){
				alert("span");
				
				//取消冒泡
				event.cancelBubble=true;
			};
			
			//为box1绑定一个单击响应函数
			var box1=document.getElementById("box1");
			box1.onclick=function(){
				alert("box1");
			};
			
			//为body绑定单击响应函数
			document.body.onclick=function(){
				alert("body");
			};
		</script>
	</body>
</html>

事件的委派

给超链接委派事件:给每一个超链接添加一个单击响应函数,但是如果我们后来再新增超链接,这些新增的超链接是没有绑定单击响应函数的。

	</head>
	<body>
		<ul id="u1">
			<li><a href="javascript:;">超链接一</a></li>
			<li><a href="javascript:;">超链接二</a></li>
			<li><a href="javascript:;">超链接三</a></li>
		</ul>
		<button id="btn1">添加超链接</button>
		
		<script type="text/javascript">
			
			var ul=document.getElementById("u1");
			
			/*点击按钮添加超链接*/
			var btn1=document.getElementById("btn1");
			btn1.onclick=function(){
				var li=document.createElement("li");
				li.innerHTML="<a href='javascript:;'>新建超链接</a>";
				ul.appendChild(li);
			};
			
			
			
			/*为每个超链接绑定一个单击响应函数,
			 为每一个超链接都绑定了一个单击响应函数,操作麻烦
			 且只能为已有的超链接设置事件,而新添加的超链接必须重新设置*/
			var allA=document.getElementsByTagName("a");
			for(var i=0;i<allA.length;++i)
			{
				allA[i].onclick=function(){
					alert("aaa");
				};
			}
		</script>
	</body>
</html>

结果:新增的超链接没有绑定单击响应函数,且我们需要为每一个超链接都绑定一次单击响应事件,太麻烦了。
在这里插入图片描述
改进:我们希望,只绑定一次事件,就可以应用到多个元素上,即使该元素是后来添加的
尝试:将其绑定给元素共同的祖先元素

			
			//为a的祖先ul绑定一个单击响应函数
			ul.onclick=function(){
				alert("1111");
			};

结果:只绑定一次,结果无论是原来的还是后来新增的都有了单击响应函数。
a标签的祖先li标签,li标签的祖先ul被绑定了单击响应函数【这就是事件冒泡的作用体现】。
事件委派:将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件
事件委派是利用了冒泡,通过委派可以减少事件的绑定次数,提供程序的性能。

在这里插入图片描述
看起来似乎解决了问题,但其实,问题有点大。
加了个背景颜色后,无论是点击绿色背景的哪个地方,都会出现委派的单击事件函数。
在这里插入图片描述
解决:判断点击的地方是不是我们想要的,不是的话就不触发。
关键代码:
//为a的祖先ul绑定一个单击响应函数
ul.οnclick=function(event){
event=event||window.event;
//event.target 表示事件触发的对象
if(event.target.className==‘link’){
alert(“111”);
}

//如果触发事件是我们期望的标签,我们就触发
};

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>显示鼠标坐标</title>
	</head>
	<body>
		<ul id="u1" style="background-color: #bfa;">
			<li><a href="javascript:;" class="link">超链接一</a></li>
			<li><a href="javascript:;" class="link">超链接二</a></li>
			<li><a href="javascript:;" class="link">超链接三</a></li>
		</ul>
		<button id="btn1">添加超链接</button>
		
		<script type="text/javascript">
			
			var ul=document.getElementById("u1");
			
			/*点击按钮添加超链接*/
			var btn1=document.getElementById("btn1");
			btn1.onclick=function(){
				var li=document.createElement("li");
				li.innerHTML="<a href='javascript:;' class='link'>新建超链接</a>";
				ul.appendChild(li);
			};
			
			
			//为a的祖先ul绑定一个单击响应函数
			ul.onclick=function(event){
				
				event=event||window.event;
				//event.target 表示事件触发的对象
				if(event.target.className=='link'){
					alert("111");
				}
					
				//如果触发事件是我们期望的标签,我们就触发
				
			};
			
			/*为每个超链接绑定一个单击响应函数,
			 为每一个超链接都绑定了一个单击响应函数,操作麻烦
			 且只能为已有的超链接设置事件,而新添加的超链接必须重新设置*/
		/*	var allA=document.getElementsByTagName("a");
			for(var i=0;i<allA.length;++i)
			{
				allA[i].οnclick=function(){
					alert("aaa");
				};
			}*/
		</script>
	</body>
</html>

事件的绑定

<script type="text/javascript">
			var btn01=document.getElementById("btn01");
			btn01,onclick=function(){
				alert("11");
			};
			btn01.onclick=function(){
				alert("2");
			};
		</script>

这样,在IE8以下,事件会被覆盖掉,后来的浏览器,都会先执行2,再执行1.
解决:addEventListener(),不支持ie8及以下的浏览器

/*addEventListener()
			 参数:
			 	1.事件的字符串,不要on
			 	2.回调函数,当事件触发时会被调用
			 	3.是否在捕获阶段触发事件,需要一个布尔值,一般穿false
			使用addEventListener()可以为同一个元素的相同事件同时绑定多个响应函数
			这样当事件被触发时,响应函数将会按照函数的绑定顺序执行】
			
			* 在IE8中不兼容,使用attachEvent()来绑定事件
			* 	参数:
			* 		1.事件的字符串,要on
			* 		2.回调函数
			* 这个方法也可以同时为一个事件绑定多个事件,不同的是它是后绑定,先执行
			* 执行顺序和addEventListener()相反*/
			
			btn01.addEventListener("click",function(){
				alert("111");
			},false)
			
			btn01.addEventListener("click",function(){
				alert("222");
			},false)
			btn01.addEventListener("click",function(){
				alert("333");
			},false)

使用addEventListener()【IE8以上或者其他浏览器才可使用】和attachEvent()【IE8及以下才可以使用】来解决,兼容性问题怎么解决?

function bind(obj,eventStr,callback){
				
			if(obj.addEventListener){
							//大部分浏览器兼容的方式
			obj.addEventListener(eventStr,callback,false);
			}
			else{
			//IE8及以下
			obj.attachEvent("on"+eventStr,function(){
			
			callback(obj);//修改this对象,本来直接传个回调函数,调用者是浏览器
			//这里我们使用匿名函数,我们在匿名函数中调用对应函数,那会调用权,
			//这样,也可以把我们的this修改为自己的对象了
			});
			}
			bind(btn01,"click",function(){
				alert("111");
			});
			

事件传播

微软公司认为事件应该由内而外传播的,也就是当事件触发时,应该先触发当前元素上的事件,然后再向当前祖先元素上传播,也就是说事件应该由里向外传【事件冒泡】;
网景公司任务事件应该是由外而内传播的,也就是先触发当前事件的祖先元素的事件,然后再向内传播给后代元素
最后W3C综合了两个公司的方案,将事件的传播分为三个阶段:
1.捕获阶段:在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,默认此时不会触发事件
2.目标阶段:事件捕获到目标元素,捕获结束后开始在目标元素上触发事件
3.冒泡阶段:事件从目标元素向祖先元素传递,依次触发祖先元素上的事件
如果希望我们在捕获阶段就触发事件,可以将addEventListener() 的第三个参数设置为true,一般情况下我们是设置为false的。
IE8一下的浏览器不会有捕获阶段。
在这里插入图片描述

事件应用

鼠标事件之拖拽

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>显示鼠标坐标</title>
		<style type="text/css">
			#box01{
				width: 200px;
				height: 200px;
				background-color: yellowgreen;
				position: absolute;
			}
			#box02{
				width: 200px;
				height: 200px;
				background-color: skyblue;
				position: absolute;
				left: 500px;
				top: 500px;
			}
		</style>
	</head>
	
	<body>
		<div id="box01"></div>
		<div id="box02"></div>
		
		<script type="text/javascript">
			
			/*
			 * 拖拽div:
			 	1.当鼠标在被拖拽元素上被按下时开启拖拽 onmousedown
			 	2.当鼠标移动时,被拖拽元素跟随鼠标移动 onmousemove
			 	3.当鼠标松开时,被拖拽元素固定在当前位置 onmouseup
			 	*/
			var box01=document.getElementById("box01");
			box01.onmousedown=function()
			{
				/*
				 当鼠标移动时被拖拽元素随鼠标移动 onmousemove
				 为document绑定一个onmousemove 事件
				 * */
				
				event=event||window.event;
				var ol = event.clientX -box01.offsetLeft;
				var ot = event.clientY -box01.offsetTop;
						
				document.onmousemove=function(event){
					event=event||window.event;
					
					var left=event.clientX;
					var top=event.clientY;
					box01.style.left=left+"px";
					box01.style.top=top+"px";
				};
				
			};
			
			//为元素绑定一个鼠标松开事件
			document.onmouseup=function(){
				//当鼠标松开时,被拖拽元素固定在当前位置
				document.onmousemove=null;//鼠标一松开,这个事件就没有意义了
				box01.onmouseup=null;//鼠标一松开,这个事件就没有意义了
			};
		</script>
	</body>
</html>

有一个bug:一取消掉document.onmouseup,第二次就会跟着鼠标一直移动。。【修了一个下午也没有找出来原因。。】

这里有个用户体验不好,我们每次点击div,最终鼠标都是跟div的左上角重合,得改进一下,鼠标和div的相对位置保持不变。
改进代码:

	var box01=document.getElementById("box01");
			box01.onmousedown=function(event)
			{
				/*
				 当鼠标移动时被拖拽元素随鼠标移动 onmousemove
				 为document绑定一个onmousemove 事件
				 * */
				event=event||window.event;
				var ol = event.clientX -box01.offsetLeft;
				var ot = event.clientY -box01.offsetTop;
						
				document.onmousemove=function(event){
					event=event||window.event;
					
					var left=event.clientX-ol;
					var top=event.clientY-ot;
					box01.style.left=left+"px";
					box01.style.top=top+"px";
				};
				
			};

鼠标事件之滚轮滚动

一个div,随着滚轮向上滚动,逐渐变大,随着滚轮向下滚动,逐渐减小。
火狐浏览器的一些方法和属性不与谷歌,ie浏览器兼容,需要另做处理。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>显示鼠标坐标</title>
		<style type="text/css">
			#box01{
				width: 200px;
				height: 200px;
				background-color: yellowgreen;
				position: absolute;
			}
		</style>
	</head>
	
	<body>
		<div id="box01"></div>
		
		<script type="text/javascript">
		
		var box01=document.getElementById("box01");
		
		/*鼠标滚轮滚动事件,会在滚轮滚动时触发
		火狐不兼容,需要使用 DOMMouseScroll()函数来绑定
		* */
		
		
		box01.onmousewheel=function(event){
			event=event||window.event;
			if(event.wheelDelta>0 || event.detail<0)
				{
					box01.style.height=box01.clientHeight-10+"px";
				}
			else
				{
					box01.style.height=box01.clientHeight+10+"px";
				}
				
			
			event.preventDefault && event.preventDefault();//判断一下,如果存在了,就执行,不然在IE8里面会报错
			//专门为火狐浏览器设置的,但是IE8不支持这个属性,如果直接调用会报错
			//判断一下,有就用,没有就不用
			
			
			/*
			 event.wheelDelta这个值不看大小,看正负【跟鼠标灵敏度有关】
			但是火狐浏览器不支持event.wheelDelta
			在火狐中,利用event.detail获取滚动方向
			*/
			
			return false;
			/*当滚轮滚动时,如果浏览器有滚动条,滚动条会随着滚动
			 这是浏览器的默认行为,如果不希望发生,取消该行为
			 但是火狐浏览器通过函数是不能够使用return false的
			 所以加上一句 event.preventDefault();*/
			
			};
			
		//为火狐浏览器绑定滚轮事件
		bind(box01,"DOMMouseScroll",box01.onmousewheel);
		
		
		
		function bind(obj,eventStr,callback){
				
			if(obj.addEventListener){
							//大部分浏览器兼容的方式
			obj.addEventListener(eventStr,callback,false);
			}
			else{
			//IE8及以下
			obj.attachEvent("on"+eventStr,function(){
			
			callback(obj);//修改this对象,本来直接传个回调函数,调用者是浏览器
			//这里我们使用匿名函数,我们在匿名函数中调用对应函数,那会调用权,
			//这样,也可以把我们的this修改为自己的对象了
			});
			}
		}
		</script>
		
	</body>
</html>

键盘事件

每个按键一按下去,都会有一个keycode编码会被接收到,js就是根据这个东西来判断是按下了哪个按键的。制作小游戏的关键。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>显示鼠标坐标</title>
		<style type="text/css">
			#box01{
				width: 100px;
				height: 100px;
				background-color: skyblue;
			}
		</style>
	</head>
	
	<body>
		<input type="text" />
	<script type="text/javascript">
		/*键盘事件:
		 onkeydown:按键被按下
		 	如果一直按着某个按键不松手,则事件会一直触发
		 	当onkeydown连续触发时,第一次和第二次时间会比较慢,其他的会非常快
		 		这种设计是为了防止误操作
		 onkeyup:按键被松开
		 键盘事件我们一般绑定给一些可以获取到焦点的对象或者是document
		 
		 */
		
		document.onkeydown=function(event){
			event=event||window.event;
			/*可以通过keycode获得按键event.keyCode
				除了keycode,还提供了alt ctrl shift是否被按下
				如果被按下,返回true。
			*/
		};
		document.onkeyup=function(){
			
		}
		
		var input=document.getElementsByTagName("input")[0];
		input.onkeydown=function(event){
			event= event||window.event;
			console.log("111");
			if(event.keyCode>=48  && event .keyCode<=57)
			//在文本框中输入文本属于onkeydown的默认行为,
			//这里可以取消默认行为
				return false;//即文本框不能输入数字
			//这里只针对笔记本电脑,如果还有小键盘,那还要继续增加条件
		}
		
		
		
		
		
		
	</script>	
	</body>
</html>

键盘的上下左右移动:

<!DOCTYPE html>
<html>
	<head>
	<meta charset="utf-8" />
	<title>显示鼠标坐标</title>
	<style type="text/css">
		#box01{
			width: 100px;
			height:100px;
			background-color: skyblue;
			position: absolute;
			/*要绝对定位才能移动*/
		}
	</style>
	</head>
	<body>
		<div id="box01"></div>
		
	<script type="text/javascript">
			//为document 绑定一个事件
			var  box01=document.getElementById("box01");
			document.onkeydown=function(event){
				event=event||window.event;
				/*37左
				 38 上
				 39右
				 40下*/
				var speed=10;
				if(event.ctrlKey)//用户按了ctrl,加快速度
					speed=50;
				switch(event.keyCode){
					case 37:
//					alert("左");
					box01.style.left=box01.offsetLeft-speed+"px";break;
					case 38:
//					alert("上");
					box01.style.top=box01.offsetTop-speed+"px";break;
					case 39:
//					alert("右");
					box01.style.left=box01.offsetLeft+speed+"px";break;
					case 40:
//					alert("下");
					box01.style.top=box01.offsetTop+speed+"px";break;
				}
			};
	</script>	
	</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值