网站首页  汉语字词  英语词汇  考试资料  写作素材  旧版资料

请输入您要查询的考试资料:

 

标题 javascript事件绑定学习要点
内容
    这篇文章主要介绍了javascript事件绑定学习要点,主要包含下面四个方面1.传统事件绑定的问题,2.W3C事件处理函数,3.IE事件处理函数,4.事件对象的其他补充,有需要的小伙伴可以参考下
    事件绑定分为两种:一种是传统事件绑定(内联模型,脚本模型),一种是现代事件绑定(DOM2级模型)。现代事件绑定在传统绑定上提供了更强大更方便的功能。
    一 传统事件绑定的问题
    传统事件绑定中的内联模型不做讨论,基本很少去用。先来看一下脚本模型,脚本模型将一个函数赋值给一个事件处理函数。传统绑定如:
    window.onload=function(){
     var box=document.getElementById('box');
     box.onclick = function(){
      alert('Lee');
     };
    };
    问题一:一个事件处理函数触发两次事件
    如果一个页面有两个或者多个js,并且第一个js是第一个程序开发的,第二个js是第二个程序员开发的。第一个window.onload被覆盖了,如
    window.onload=function(){
     alert('Lee');
    };
    window.onload=function(){
     alert('Mr.lee');
    } 
    结果只是打印了 Mr.lee
    其实是有办法解决这个问题的,看下面这两种形式。
    a:
    alert(window.onload);//一开始没有注册window.onload,那么就是null
    window.onload=function(){
     alert('Lee');
    };
    alert(window.onload);//如果已经有window.onload,打印的是函数function
    window.onload=function(){
     alert('Mr.lee');
    } 
    b:
    alert(typeof window.onload);//一开始没有window.onolad,旧版火狐显示undefined,新版显示object,
    window.onload=function(){
     alert('Lee');
    };
    alert(typeof window.onload);//如果已经有window.onload,所有浏览器都会显示function
    window.onload=function(){
     alert('Mr.lee');
    }
    所以解决办法有了。
    window.onload=function(){
     alert('Lee');
    };
    if(typeof window.onload=='function'){
     var saved=null;//保存上一个事件对象
     saved=window.onload;
    }
    //saved 就是window.onload,saved()相当于window.onload(),但是window.onload()不能执行的
    //所以saved()相当于window.onload=function(){}
    window.onload=function(){
     if(saved){
      saved();//执行上一个事件 window.onload=function(){}
     }
     alert('Mr.lee'); //执行本事件
    }
    问题二:事件切换器
    切换一个id为box的div,让里面的背景red与blue直接切换,并且切换之前弹框一次,如:
    window.onload=function(){
     var box=document.getElementById('box');
     box.className="red";
     box.onclick=function(){
      alert('Lee'); //只执行了一次
      blue.call(this);//通过匿名函数执行某一函数,那么里面的this就是代表的window,所以可以通过call传递
     };
    }
    function blue(){
     this.className="blue";
     this.onclick=red;
    }
    function red(){
     this.className="red";
     this.onclick=blue;
    }
    上面的代码虽然实现了切换功能,但是弹框只执行了一次。
    //添加事件函数
    //obj相当于window
    //type相当于onload
    //fn相当于function(){}
    function addEvent(obj,type,fn){
     //用于保存上一个事件
     var saved=null;
     if(typeof obj['on'+type]=='function'){
      saved=obj['on'+type];//保存上一个事件
     }
     obj['on'+type]=function(){
      if(saved){
       saved();
      }
      fn.call(this);
     }
    }
    addEvent(window,'load',function(){
     var box=document.getElementById("box");
     //addEvent(box,'click',function(){ //目的达到,每次都执行了,没有被覆盖
     // alert('ss');
     //});
     addEvent(box,'click',blue);
    });
    function red(){
     this.className="red";
     addEvent(box,'click',blue);
    }
    function blue(){
     this.className="blue";
     addEvent(box,'click',red);
    }
    //当不停的切换的时候,浏览器突然卡死,并且报错:too much recursion,太多的递归
    //因为积累了太多的保存的事件
    //解决方案,就是用完的事件,就立刻移除掉
    按照上面的代码出现了注释中的错误,解决的办法如下:
    //添加事件函数
    //obj相当于window
    //type相当于onload
    //fn相当于function(){}
    function addEvent(obj,type,fn){
     //用于保存上一个事件
     var saved=null;
     if(typeof obj['on'+type]=='function'){
      saved=obj['on'+type];//保存上一个事件
     }
     obj['on'+type]=function(){
      if(saved){
       saved();
      }
      fn.call(this);
     }
    }
    //当不停的切换的时候,浏览器突然卡死,并且报错:too much recursion,太多的递归
    //因为积累了太多的保存的事件
    //解决方案,就是用完的事件,就立刻移除掉
    //移除事件函数
    function removeEvent(obj,type){
     if(obj['on'+type]){
      obj['on'+type]=null;
     }
    }
    addEvent(window,'load',function(){
     var box=document.getElementById("box");
     //addEvent(box,'click',function(){ //目的达到,每次都执行了,没有被覆盖
     // alert('ss');
     //});
     addEvent(box,'click',blue);
    });
    function red(){
     this.className="red";
     removeEvent(this,'click');
     addEvent(box,'click',blue);
    }
    function blue(){
     this.className="blue";
     removeEvent(this,'click');
     addEvent(box,'click',red);
    }
    二 W3C事件处理函数
    addEventListener()与removeEventListener()
    W3C事件处理函数两个,addEventListener()与removeEventListener()。
    //W3C自带的两个添加事件和删除事件
    1.覆盖问题,解决
    window.addEventListener('load',function(){
     alert('Lee');
    },false);
    window.addEventListener('load',function(){
     alert('Mr.Lee');
    },false);
    window.addEventListener('load',function(){
     alert('Mrs.Lee');
    },false);
    2.相同函数屏蔽的问题,解决
    window.addEventListener('load',init,false);
    window.addEventListener('load',init,false);
    window.addEventListener('load',init,false);
    function init(){
     alert('Lee');
    }
    3.是否可以传递this,解决
    例子1:
    window.addEventListener('load',function(){
     var box=document.getElementById('box');
     box.addEventListener('click',function(){
      alert(this);
     },false);
    },false);
    例子2:
    window.addEventListener('load',function(){
     var box=document.getElementById('box');
     box.addEventListener('click',blue,false);
    },false);
    function red(){
     this.className="red";
     this.removeEventListener('click',red,false);
     this.addEventListener('click',blue,false);
    }
    function blue(){
     this.className="blue";
     this.removeEventListener('click',blue,false);
     this.addEventListener('click',red,false);
    }
    4.添加一个额外的方法,会不会被覆盖,或者只能执行一次,解决
    window.addEventListener('load',function(){
     var box=document.getElementById('box');
     box.addEventListener('click',function(){
      alert('Lee');
     },false);
     box.addEventListener('click',blue,false);
    },false);
    综上所述:W3C是比较完美的解决了这些问题,非常好用,但是IE8和之前的浏览器并不支持,而是采用了自己的事件,当然IE9已经完全支持了W3C的这两个事件处理函数。
    W3C可以设置冒泡和捕获方式。
    支持W3C标准的浏览器在添加事件时用addEventListener(event,fn,useCapture)方法,基中第3个参数useCapture是一个Boolean值,用来设置事件是在事件捕获时执行,还是事件冒泡时执行。而不兼容W3C的浏览器(IE)用attachEvent()方法,此方法没有相关设置,不过IE的事件模型默认是在事件冒泡时执行的,也就是在useCapture等于false的时候执行,所以把在处理事件时把useCapture设置为false是比较安全,也实现兼容浏览器的效果。
    事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)。
    事件冒泡阶段:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签。
    事件的传播是可以阻止的:
    在W3c中,使用stopPropagation()方法
    在IE下设置cancelBubble = true;
    三.IE事件处理函数
    attachEvent()和detachEvent()
    IE实现了与DOM中类似的两个方法:attachEvent()和detachEvent()。这两个方法接受相同的参数:事件名称和函数。
    在使用这两组函数的时候,先把区别说一下:1.IE不支持捕获,只支持冒泡;2.IE添加事件不能屏蔽重复的函数;3.IE中的this指向的是window而不是DOM对象。4.在传统事件上,IE是无法接受到event对象的,但使用了attchEvent却可以,但有些区别。
    1.覆盖问题,解决了,但有不同,结果是Mrs.Lee,Mr.Lee,最后是Lee
    window.attachEvent('onload',function(){
     alert('Lee');
    });
    window.attachEvent('onload',function(){
     alert('Mr.Lee');
    });
    window.attachEvent('onload',function(){
     alert('Mrs.Lee');
    });
    2.相同函数屏蔽的问题,未解决。
    window.attachEvent('onload',init);
    window.attachEvent('onload',init);
    function init(){
     alert('Lee');
    }
    3.是否可以传递this,不能,this指的是window。需要用call方法。
    window.attachEvent('onload',function(){
     var box=document.getElementById('box');
     box.attachEvent('onclick',function(){
      //alert(this===box);
      alert(this===window); //true
     });
    });
    下面还有办法就是通过window.event.srcElement。代码如下:
    window.attachEvent('onload',function(){
     var box=document.getElementById('box');
     box.attachEvent('onclick',blue);
    });
    function red(){
     var that=window.event.srcElement;
     that.className="red";
     that.detachEvent('onclick',red);
     that.attachEvent('onclick',blue);
    }
    function blue(){
     var that=window.event.srcElement;
     that.className="blue";
     that.detachEvent('onclick',blue);
     that.attachEvent('onclick',red);
    }
    4.添加一个额外的方法,会不会被覆盖,或者只能执行一次,解决。
    在传统绑定上,IE是无法像W3C那样通过传参接受event对象,但是使用attachEvent()却可以。
    window.attachEvent('onload',function(){
     var box=document.getElementById('box');
     box.onclick=function(evt){ //传统方法IE无法通过参数获取evt
      alert(evt);//undefined
     }
     box.attachEvent('onclick',function(evt){
      alert(evt);//object
      alert(evt.type);//click
      alert(evt.srcElement.tagName);//DIV
      alert(window.event.srcElement.tagName);//DIV
     });
    });
    跨浏览器的兼容
    跨浏览器添加事件
    function addEvent(obj,type,fn){
     if(obj.addEventListener){
      obj.addEventListener(type,fn,false);
     }else if(obj.attachEvent){
      obj.attachEvent('on'+type,fn);
     }
    }
    跨浏览器移除事件
    function removeEvent(obj,type,fn){
     if(obj.removeEventListener){
      obj.removeEventListener(type,fn,false);
     }else if(obj.detachEvent){
      obj.detachEvent('on'+type,fn);
     }
    }
    跨浏览器获取目标对象
    function getTarget(evt){
     if(evt.target){
      return evt.target;
     }else if(window.event.srcElement){
      return window.event.srcElement;
     }
    }
    调用方式:
    addEvent(window,'load',function(){
     var box=document.getElementById('box');
     addEvent(box,'click',blue);
    });
    function red(evt){
     var that=getTarget(evt);
     that.className="red";
     removeEvent(that,'click',red);
     addEvent(that,'click',blue);
    }
    function blue(evt){
     var that=getTarget(evt);
     that.className="blue";
     removeEvent(that,'click',blue);
     addEvent(that,'click',red);
    }
    四.事件对象的其他补充
    relatedTarget事件
    w3c中的一个relatedTarget事件。
    例如:
    addEvent(window,'load',function(){
     var box=document.getElementById('box');
     addEvent(box,'mouseover',function(evt){
      alert(evt.relatedTarget); //得到移入box最近的那个DOM对象
     });
     addEvent(box,'mouseout',function(evt){
      alert(evt.relatedTarget); //从box移出最近的那个DOM对象
     });
    });
    IE提供了两组分别用于移入移出的属性fromElement和toElement,分别对应mouseover和mouseout。
    addEvent(window,'load',function(){
     var box=document.getElementById('box');
     addEvent(box,'mouseover',function(){
      alert(window.event.fromElement.tagName); //得到移入box最近的那个DOM对象
     });
     addEvent(box,'mouseout',function(){
      alert(window.event.toElement.tagName); //从box移出最近的那个DOM对象
     });
    });
    PS:fromElement和toElement如果分别对应相反的鼠标事件,没有任何意义。
    剩下要做的就是跨浏览器兼容操作:
    function getTarget(evt){
     var e=evt || window.event;
     if(e.srcElment){ //IE
      if(e.type=='mouseover'){
       return e.fromElement.tagName;
      }else if(e.type="mouseout"){
       return e.toElement.tagName;
      }
     }else if(e.relatedTarget){ //w3c
      return e.relatedTarget;
     }
    }
    屏蔽跳转操作
    取消事件的默认行为有一种不规范的做法,就是返回false。
    link.onclick=function(){
     alert('Lee');
     return false;
    }
    PS:虽然return false;可以实现这个功能,但是有漏洞。
    第一:必须写到最后,这样导致中奖的代码执行后,有可能执行不到return false;
    第二:return false 写到最前那么之后的自定义操作就失效了。
    所以最好的办法应该是在最前面就阻止默认行为,并且后面的代码还可以执行。
    link.onclick=function(evt){
     evt.preventDefault;//w3c,阻止默认行为
     alert('Lee');
    }
    link.onclick=function(evt){
     window.event.returnValue=false;//IE,阻止默认行为
     alert('Lee');
    }
    那么跨浏览器的兼容:
    function preDef(evt){
     var e=evt || window.event;
     if(e.preventDefault){
      e.preventDefault();
     }else{
      e.returnValue=false;
     }
    }
    右键菜单contextmenu
    兼容:
    function preDef(evt){
     var e=evt || window.event;
     if(e.preventDefault){
      e.preventDefault();
     }else{
      e.returnValue=false;
     }
    }
    addEvent(window,"load",function(){
     var body=document.getElementsByTagName('body')[0];
     addEvent(body,'contextmenu',function(evt){
      preDef(evt);
     })
    });
    PS:contextmenu事件很常用,这直接导致浏览器兼容性较为稳定。
    卸载前事件:beforeunload
    这个事件可以帮助在离开本页的时候给出相应的提示,“离开”或者“返回”操作。
    addEvent(window,'beforeonload',function(){
     preDef(evt);
    });
    鼠标滚轮(mousewheel)和DOMMouseScroll
    用于获取鼠标上下滚轮的距离
    addEvent(document,'mousewheel',function(evt){ //非火狐
     alert(getWD(evt));
    });
    addEvent(document,'DOMMouseScroll',function(evt){ //火狐
     alert(getWD(evt));
    });
    function getWD(evt){
     var e=evt|| window.event;
     if(e.wheelDelta){
      return e.wheelDelta;
     }else if(e.detail){ //火狐
      return -evt.detail*30;
     }
    }
    PS:通过浏览器检测可以确定火狐只执行DOMMouseScroll。
    DOMContentLoaded事件和readystatechange事件
    DOMContentLoaded事件和readystatechange事件,有关DOM加载方面的事件。
随便看

 

在线学习网考试资料包含高考、自考、专升本考试、人事考试、公务员考试、大学生村官考试、特岗教师招聘考试、事业单位招聘考试、企业人才招聘、银行招聘、教师招聘、农村信用社招聘、各类资格证书考试等各类考试资料。

 

Copyright © 2002-2024 cuapp.net All Rights Reserved
更新时间:2025/5/19 7:46:46