一,鼠标手动触发事件

这类事件是我们最常用,也是动作交互的核心。

1.单击事件与双击事件

click事件的绑定:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:100px; background:#0C3;" id="ele1"></div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 ele1.onclick=function(){
  console.log(1);
 };
</script>
</html>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:100px; background:#0C3;" id="ele1"></div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 ele1.onclick=function(){
  console.log(1);
 };
</script>
</html>

监听后,我们的触发条件就是点击这个元素,每次点击都触发一次回调处理。我们按下后长按发现是不会输出内容的,只有在鼠标抬起后执行绑定函数,说明click事件的触发点在鼠标抬起后。

除了单击,我们在操作系统中还有双击事件:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:100px; background:#0C3;" id="ele1"></div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 ele1.ondblclick=function(){
  console.log(1);
 };
</script>
</html>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:100px; background:#0C3;" id="ele1"></div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 ele1.ondblclick=function(){
  console.log(1);
 };
</script>
</html>

必须在较短时间点击2次才会触发。

2.鼠标组合事件

click事件我们设想一下其实一般包含三步操作,鼠标按下,移动(可有可无),抬起。

我们分别监听三个事件:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:100px; background:#0C3;" id="ele1"></div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 ele1.onmousedown=function(){
  console.log(1);
 };
 ele1.onmousemove=function(){
  console.log(2);
 };
 ele1.onmouseup=function(){
  console.log(3);
 };
</script>
</html>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:100px; background:#0C3;" id="ele1"></div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 ele1.onmousedown=function(){
  console.log(1);
 };
 ele1.onmousemove=function(){
  console.log(2);
 };
 ele1.onmouseup=function(){
  console.log(3);
 };
</script>
</html>

move事件只要移动就会触发,但是按下事件的下一次触发必须在抬起事件之后,也就是一次click完成之后。

我们按下后不动,保持长按其实只会触发一次按下事件。

3.单击事件的冒泡

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:100px; background:#0C3;" id="ele1">
    <div style="height:100px; width:100px; background:#000;" id="ele2">
    
    </div>
</div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 var ele2=document.getElementById("ele2");
 ele2.onclick=function(){
  alert(2);
 };
 ele1.onclick=function(){
  alert(1);
 }; 
 
</script>
</html>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:100px; background:#0C3;" id="ele1">
    <div style="height:100px; width:100px; background:#000;" id="ele2">
    
    </div>
</div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 var ele2=document.getElementById("ele2");
 ele2.onclick=function(){
  alert(2);
 };
 ele1.onclick=function(){
  alert(1);
 }; 
 
</script>
</html>

先执行内部在执行外部,如果我们内部是让某个div显示,外部是让那个div隐藏,这样就发生了冲突,不能实现点击内部div去隐藏,我们可以利用事件对象去阻止冒泡:

ele2.onclick=function(event){
  alert(2);
  event.stopPropagation();
 };
ele2.onclick=function(event){
  alert(2);
  event.stopPropagation();
 };

点击内部div,事件执行后阻止往上查找父辈元素的绑定处理。

4.事件委托

委托的原理就是来自冒泡,还是上面的例子,我们在外部div里有3个div,其实点击三个内部div哪一个都会点击到外部div,所以我们就可以把每个内部div的事件绑定统一绑定到外部div上,然后利用标志区分去触发相应函数。

我们先看最普通的处理方式,分别绑定:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:100px; background:#0C3;" id="ele1">
    <div style="height:30px; width:100px; background:#000;" id="ele2">
    
    </div>
    <div style="height:30px; width:100px; background:#399;" id="ele3">
    
    </div>
    <div style="height:30px; width:100px; background:#03F;" id="ele4">
    
    </div>
</div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 var ele2=document.getElementById("ele2");
 var ele3=document.getElementById("ele3");
 var ele4=document.getElementById("ele4");
 ele2.onclick=function(event){
  alert(2);
 };
 ele3.onclick=function(){
  alert(3);
 }; 
 ele4.onclick=function(){
  alert(4);
 };
 
</script>
</html>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:100px; background:#0C3;" id="ele1">
    <div style="height:30px; width:100px; background:#000;" id="ele2">
    
    </div>
    <div style="height:30px; width:100px; background:#399;" id="ele3">
    
    </div>
    <div style="height:30px; width:100px; background:#03F;" id="ele4">
    
    </div>
</div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 var ele2=document.getElementById("ele2");
 var ele3=document.getElementById("ele3");
 var ele4=document.getElementById("ele4");
 ele2.onclick=function(event){
  alert(2);
 };
 ele3.onclick=function(){
  alert(3);
 }; 
 ele4.onclick=function(){
  alert(4);
 };
 
</script>
</html>

我们在使用委托的处理机制:

ele1.onclick=function(event){
  var tar=event.target;
  if(tar.id=="ele2"){
   alert(2);
  }else if(tar.id=="ele3"){
   alert(3);
  }else if(tar.id=="ele4"){
   alert(4);
  }else{
   alert(1);
  };
 };
ele1.onclick=function(event){
  var tar=event.target;
  if(tar.id=="ele2"){
   alert(2);
  }else if(tar.id=="ele3"){
   alert(3);
  }else if(tar.id=="ele4"){
   alert(4);
  }else{
   alert(1);
  };
 };

利用event.target获取最小触发元素,根据id的区别做了判断处理,是不是省去很多绑定事件的代码。

5.获取焦点和失去焦点

同click事件类似:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:200px; background:#0C3;" id="ele1">
    <input type="text" id="ele2" >
</div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 var ele2=document.getElementById("ele2");
 ele2.onfocus=function(event){
  console.log(1);
 };
 ele2.onblur=function(event){
  console.log(2);
 };  
 
</script>
</html>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:200px; background:#0C3;" id="ele1">
    <input type="text" id="ele2" >
</div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 var ele2=document.getElementById("ele2");
 ele2.onfocus=function(event){
  console.log(1);
 };
 ele2.onblur=function(event){
  console.log(2);
 };  
 
</script>
</html>

6.不是所有事件都可以冒泡

上面我们测试了获取焦点事件,我们看看可以冒泡吗?

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:200px; background:#0C3;" id="ele1">
    <input type="text" id="ele2" >
</div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 var ele2=document.getElementById("ele2");
 ele2.onfocus=function(event){
  console.log(1);
 };  
 ele1.onfocus=function(event){
  console.log(2);
 };
</script>
</html>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:200px; background:#0C3;" id="ele1">
    <input type="text" id="ele2" >
</div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 var ele2=document.getElementById("ele2");
 ele2.onfocus=function(event){
  console.log(1);
 };  
 ele1.onfocus=function(event){
  console.log(2);
 };
</script>
</html>

是不是不会输出父元素的内容,因为父元素是不具备焦点事件的,

7.鼠标组合事件模拟拖拽实现

页面一个div可以拖拽移动,先说原理,我们会先按下(拖拽div),然后移动(拖拽div跟随),最后抬起(拖拽div静止)。

整个流程每次要发生在一套click的内部:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div id="drag" style="width:200px; height:200px; top:200px; left:400px; background:#990; position:absolute; padding:100px;">
 登录<input type="text" /><br/>
    密码<input type="text" /><br/>
    <input type="button" value="ok" />
</div>
</body>
<script type="text/javascript">
window.onload=function(){
  var drag=document.getElementById("drag"); 
  var isd=0; 
  var elex=0;
  var eley=0;
  drag.onmousedown=function(event){ 
   isd=1;  
   elex=event.clientX-drag.offsetLeft;
   eley=event.clientY-drag.offsetTop; 
  };
  drag.onmousemove=function(event){ 
   if(isd==1){
    var evx=event.clientX;
    var evy=event.clientY;
    var cx=evx-elex;
    var cy=evy-eley;
    drag.style.left=cx+"px";
    drag.style.top=cy+"px";
  
   }else{}    
  };
  drag.onmouseup=function(event){  
   isd=0;
  };    
};
</script>
</html>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div id="drag" style="width:200px; height:200px; top:200px; left:400px; background:#990; position:absolute; padding:100px;">
 登录<input type="text" /><br/>
    密码<input type="text" /><br/>
    <input type="button" value="ok" />
</div>
</body>
<script type="text/javascript">
window.onload=function(){
  var drag=document.getElementById("drag"); 
  var isd=0; 
  var elex=0;
  var eley=0;
  drag.onmousedown=function(event){ 
   isd=1;  
   elex=event.clientX-drag.offsetLeft;
   eley=event.clientY-drag.offsetTop; 
  };
  drag.onmousemove=function(event){ 
   if(isd==1){
    var evx=event.clientX;
    var evy=event.clientY;
    var cx=evx-elex;
    var cy=evy-eley;
    drag.style.left=cx+"px";
    drag.style.top=cy+"px";
  
   }else{}    
  };
  drag.onmouseup=function(event){  
   isd=0;
  };    
};
</script>
</html>

慢慢的拖动好像没问题,但是我们快速移动鼠标,鼠标脱离拖拽体,就出现问题了,在移入就粘连了,我们的问题就是把move和up事件也绑定在了拖拽体上,我们修改对象,绑定到html对象上:

window.onload=function(){
  var drag=document.getElementById("drag"); 
  var isd=0; 
  var elex=0;
  var eley=0;
  drag.onmousedown=function(event){ 
   isd=1;  
   elex=event.clientX-drag.offsetLeft;
   eley=event.clientY-drag.offsetTop; 
  };
  document.documentElement.onmousemove=function(event){ 
   if(isd==1){
    var evx=event.clientX;
    var evy=event.clientY;
    var cx=evx-elex;
    var cy=evy-eley;
    drag.style.left=cx+"px";
    drag.style.top=cy+"px";
  
   }else{}    
  };
  document.documentElement.onmouseup=function(event){  
   isd=0;
  };    
};
window.onload=function(){
  var drag=document.getElementById("drag"); 
  var isd=0; 
  var elex=0;
  var eley=0;
  drag.onmousedown=function(event){ 
   isd=1;  
   elex=event.clientX-drag.offsetLeft;
   eley=event.clientY-drag.offsetTop; 
  };
  document.documentElement.onmousemove=function(event){ 
   if(isd==1){
    var evx=event.clientX;
    var evy=event.clientY;
    var cx=evx-elex;
    var cy=evy-eley;
    drag.style.left=cx+"px";
    drag.style.top=cy+"px";
  
   }else{}    
  };
  document.documentElement.onmouseup=function(event){  
   isd=0;
  };    
};

用金星老师话说配合姿势,这就是完美!在组合处理中选择正确的绑定元素至关重要。

二,键盘触发事件

主要输入设备除了鼠标还有就是键盘。

键盘有啥?按下,长按,抬起,我们分别绑定:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:200px; background:#0C3;" id="ele1" contenteditable="true">
    <input type="text" id="ele2" >
</div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 var ele2=document.getElementById("ele2");
 ele2.onkeydown=function(event){
  console.log(1);
 }; 
 ele2.onkeypress=function(event){
  console.log(2);
 };
 ele2.onkeyup=function(event){
  console.log(3);
 }; 
</script>
</html>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
</head>
<body>
<div style="height:100px; width:200px; background:#0C3;" id="ele1" contenteditable="true">
    <input type="text" id="ele2" >
</div>
</body>
<script type="text/javascript">
 var ele1=document.getElementById("ele1");
 var ele2=document.getElementById("ele2");
 ele2.onkeydown=function(event){
  console.log(1);
 }; 
 ele2.onkeypress=function(event){
  console.log(2);
 };
 ele2.onkeyup=function(event){
  console.log(3);
 }; 
</script>
</html>

按下事件的每次触发也是在本次抬起结束后。

三,异步事件

这个名字是我自己起的,原因就是这些事件的触发要经过一段时间,去判断某个状态是否达到。

1.load载入完成事件

我们在看别人的js是这样的:

window.onload=function(){
 var ele1=document.getElementById("ele1");
 var ele2=document.getElementById("ele2");
 ele2.onkeydown=function(event){
  console.log(1);
 }; 
 ele2.onkeypress=function(event){
  console.log(2);
 };
 ele2.onkeyup=function(event){
  console.log(3);
 }; 
};
window.onload=function(){
 var ele1=document.getElementById("ele1");
 var ele2=document.getElementById("ele2");
 ele2.onkeydown=function(event){
  console.log(1);
 }; 
 ele2.onkeypress=function(event){
  console.log(2);
 };
 ele2.onkeyup=function(event){
  console.log(3);
 }; 
};

加入load事件,那么里面的程序就会在页面html加载完执行,避免无结构先发生处理。

load的重要在图片处理上是非常的重要,现在css3盛行,我们会加入很多动画处理,动画处理会用到很多图片,假如用到了4张,如果图片没加载完,我们动画执行了,客户怎么看?这时候我们就要对5张图都进行load完成判断,确定4张ok才去引入动画css是不是。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
    <style type="text/css">
 /*reset*/
 *{ padding:0; margin:0}
 body{ height: 100%; width: 100%; font-size:12px; color:#333;}
 ul{ list-style:none;}
 /*demo*/
 .box{width: 900px;margin: 0 auto;}
 .box img{ width: 200px;height: 200px;margin: 10px;border: 1px solid #000;}
 </style>
</head>
<body>
<div class="box">
     <img src="http://fe.topit.me/e/53/65/11639567172a86553eo.jpg" class="readyimg ready1">
     <img src="http://www.pp3.cn/uploads/allimg/111116/1102135I3-12.jpg" class="readyimg ready2">
     <img src="http://i5.topit.me/5/d1/9b/1132725126ff69bd15o.jpg" class="readyimg ready3">
     <img src="http://f9.topit.me/9/31/41/113272518184741319o.jpg" class="readyimg ready4">     
    </div>
</body>
<script type="text/javascript">
  var imgo=document.querySelectorAll(".readyimg");
  var imglen=imgo.length;
  var isimg=[];
  for(var i=0;i<imglen;i++){
   isimg[i]=0;
  };
  for(var i=0;i<imglen;i++){
   
   (function(i){
    imgo[i].onload=function(){
  isimg[i]=1;
  ifready();
    };
   })(i);
    
  };
  function ifready(){
   if(isready()==1){
    alert('图片全部加载完!当前放入处理代码')
   }else{
  
   };
  };
  function isready(){
   var res=1;
   for(var i=0;i<imglen;i++){
    if(isimg[i]==0){
  res=0;
    }else{};
   };
   return res;
  };
</script>
</html>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>js</title>
    <style type="text/css">
 /*reset*/
 *{ padding:0; margin:0}
 body{ height: 100%; width: 100%; font-size:12px; color:#333;}
 ul{ list-style:none;}
 /*demo*/
 .box{width: 900px;margin: 0 auto;}
 .box img{ width: 200px;height: 200px;margin: 10px;border: 1px solid #000;}
 </style>
</head>
<body>
<div class="box">
     <img src="http://fe.topit.me/e/53/65/11639567172a86553eo.jpg" class="readyimg ready1">
     <img src="http://www.pp3.cn/uploads/allimg/111116/1102135I3-12.jpg" class="readyimg ready2">
     <img src="http://i5.topit.me/5/d1/9b/1132725126ff69bd15o.jpg" class="readyimg ready3">
     <img src="http://f9.topit.me/9/31/41/113272518184741319o.jpg" class="readyimg ready4">     
    </div>
</body>
<script type="text/javascript">
  var imgo=document.querySelectorAll(".readyimg");
  var imglen=imgo.length;
  var isimg=[];
  for(var i=0;i<imglen;i++){
   isimg[i]=0;
  };
  for(var i=0;i<imglen;i++){
   
   (function(i){
    imgo[i].onload=function(){
  isimg[i]=1;
  ifready();
    };
   })(i);
    
  };
  function ifready(){
   if(isready()==1){
    alert('图片全部加载完!当前放入处理代码')
   }else{
  
   };
  };
  function isready(){
   var res=1;
   for(var i=0;i<imglen;i++){
    if(isimg[i]==0){
  res=0;
    }else{};
   };
   return res;
  };
</script>
</html>

只有在4张图被载入完才会执行处理,我们每次测试ctrl+f5可以测试。

2.ajax事件

xmlhttp.onreadystatechange

四,其他事件

上面都是最常用事件,js为我们的交互提供的事件是非常多的,移动端的touch事件,音视频的播放事件,卸载事件,关闭窗口事件等等等。