论坛首页 Web前端技术论坛

关于IE和Firefox下event乱谈

浏览 13717 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-06-02  
        如果在使用javascript的时候涉及到event处理,就需要知道event在不同的浏览器中的差异,因为javascript的事件模型有三种,它们分别是NN4、IE4+和W3C/Safari;这也造成了在不同的浏览器中处理event的差异,这里结合一些零碎的代码来说明如何做到event在IE4+和Firefox下的正常工作。首先看如下代码:
  1. function doEventThing(eventTag){   
  2.    var event = eventTag||window.event;   
  3.    var currentKey = event.charCode||event.keyCode;   
  4.    var eventSource =window.event.srcElement||eventTag.target;   
  5. }  
       这段代码主要是为了处理键盘事件的,在IE中event作为window对象的一个属性可以直接使用,但是在Firefox中却使用了W3C的模型,它是通过传参的方法来传播事件的,也就是说你需要为你的函数提供一个事件响应的接口,在上述函数中,
eventTag扮演的就是这个角色。
             var event = eventTag||window.event;
             这段代码可以根据浏览器的不同来得到正确的event,并在程序中使用,如果在IE4+下面使用这段代码,因为eventTag为null可以保证event = window.event,但是如果在Firefox下运行的话则因为手工的给定了eventTag所以var event = eventTag。根据对这一段代码的分析我们也不难看出可以对doEventThing方法进行如下的改造(因为javascript允许我们在定义function的时候不明确指出参数的数量):
  1. function doEventThing(){   
  2.     var event = arguments[0]||window.event;   
  3.      //other code   
  4. }  
在Firefox下arguments[0]在特定的场合(没有显式的指定function参数数量的时候)被做为传播事件的参数来使用…………
      至于var currentKey = event.charCode||event.keyCode;也是不同的浏览器所致,在IE4+下面记录键盘的是keyCode,但是在Firefox下的却是charCode,为此我们需要处理他们的差异。
     还有一个差异就是事件源的获取:通过语句var eventSource = window.event.srcElement||eventTag.target;我们也看到了IE与W3C的不同。
     经过上面的包装,我们基本上可以在IE4+和Firefox下面顺利的使用事件机制了,当然如果为了通用性可以对这种差异进封装来形成自己的Event对象在程序中误差别的使用事件对象,这里就不在介绍了。
   
     接下来分析事件的绑定:大概分为如下5种
     1、绑定到元素,这也是比较常见的一种比如:
  1. <input type="button" onclick="doEventThing(event)">  

,这样我们就把doEventThing绑定到了该button对象上,点击此按钮事件就被触发。
    2、绑定事件到对象:这也是比较常见的一种,特别是在IE4+下面:
                 document.getElementById("divid").onclick = doEventThing;
   3、使用<script for="">进行事件的绑定,这只在IE4+下有用(为buttong1绑定事件,逻辑在script块中书写event来指定怎么触发事件):
                 <script for="button1" event="onclick">
                     // script statements here
                  </script>
   4、使用 IE5/Windows 的 attachEvent() 方法     
   5、使用 W3C DOM 的 addEventListener() 方法
              addEventListener("eventType",listenerReference,captureFlag);
              第三个参数则是一个 Boolean 值,指明该结点是否以DOM中所谓的捕捉模式来侦听事件。对于一个典型的事件侦听器来说,第三个参数应该为false(假)。

  prototype在绑定事件的时候兼容IE和W3C的时候做的处理如下:
  1. _observeAndCache: function(element, name, observer, useCapture) {   
  2.    if (!this.observers) this.observers = [];   
  3.    if (element.addEventListener) {//W3C DOM   
  4.      this.observers.push([element, name, observer, useCapture]);   
  5.      element.addEventListener(name, observer, useCapture);   
  6.    } else if (element.attachEvent) {//IE5/Windows   
  7.      this.observers.push([element, name, observer, useCapture]);   
  8.      element.attachEvent('on' + name, observer);   
  9.    }   
  10. }  
撇开this.observers.pust([element,name,observer,useCapture])不谈,我们对4、5所说的事件绑定就很清楚了。我们知道prototype的此方法的useCapture在IE下没有作用,只对W3C的事件处理机制起作用。
   发表时间:2007-06-02  
attachEvent,addEventListener还有个麻烦的区别,attachEvent绑定的函数,没有绑定this引用.
0 请登录后投票
   发表时间:2007-06-02  
jindw 写道
attachEvent,addEventListener还有个麻烦的区别,attachEvent绑定的函数,没有绑定this引用.

不知道我的理解是否和你说的是一个话题,请看代码如下:
function doIt(){
   alert(this);
}

然后我们在页面中处理如下:
首先做一个按钮:<button id="btn">按钮</button>,然后为该按钮绑定事件onclick如下:
<script language="javascript" type="text/javascript">
document.getElementById("btn4").attachEvent("onclick",doIt);
</script>


经过这种处理之后,doIt方法中的this不代表button,但是使用
      document.getElementById("btn4").onclick = doIt时this指向的就是btn代表的button了,
     还有就是
      document.getElementById("btn4").addEventListener('click',doSomething,false);这样也可以把this绑定进去(FF下面),这种情况不知道该怎么解决…………
不过测试后可以发现:
      如果使用了:attacchEvent,则this代表的对象包含如下属性,应该是window:
onbeforeunload   onafterprint   top   location   parent  
offscreenBuffering   frameElement   onerror   screen   event  
clipboardData   onresize   defaultStatus   onblur   window  
onload   onscroll   screenTop   onfocus   Option  
length   onbeforeprint   frames   self   clientInformation  
external   screenLeft   opener   onunload   document  
closed   history   Image   navigator   status  
onhelp   name
0 请登录后投票
   发表时间:2007-06-02  
基本是这个意思吧:)
attachEvent只是记录了函数,函数运行时不知道元素时那个.
addEventListener做的好些,运行时,this是指向被绑的对象,如你上面的那个btn.

我感觉这个this还是有很大用处的,运行时可以知道元素,而ie就很麻烦,ID?或者通过闭包吧元素也绑进去,但是,这样就是一个循环引用,有内存泄漏问题.


现在常用的一些脚本库,大多都没有重视这点区别.
我在JSI API里,写了个js.html.EventUtil
里面消除了这种区别.
0 请登录后投票
   发表时间:2007-06-02  
在javascript中this是一个很辣手的问题所以,我在实际的处理过程中总是会尽量的避免这样使用:
  function(){
     this.style.…………;//这里只是简单的说明哦
  }
而更倾向于使用:
  function(needObj){
     needObj.style.…………;
  }
0 请登录后投票
   发表时间:2007-06-02  
关于这个事件目前我知道的解决的最好的脚本是这个:http://therealcrisp.xs4all.nl/upload/addEvent2.html
0 请登录后投票
   发表时间:2007-06-02  
可以参考objot的event handler,解决得很好。ff和ie下使用一致,而且很容易消除ie6的内存泄漏
var x = $dom($id('elementId'));
var data = ...;
$this(x.attach('onclick', onClick), data);

function onClick(event) {
  alert(event.target); // == srcElement
  alert(event.charCode); // == keyCode
  alert(event.stop); // function, == stopPropagation, or == (cancelBubble = true)
  alert(this); // == data,$this传入的参数,如果无$this,则为dom元素
  event.target.des(); // 如果这个dom元素不需要了,清除之,并清除内存泄漏
}


每个dom元素清除泄漏的时间是常量,而且一并清除所有子元素,方便组件化开发
0 请登录后投票
   发表时间:2007-06-04  
补充:

attachEvent的this问题非常讨厌,因为它导致你不能很好的使用bubble了,因为你不知道当前事件bubble到哪个元素上。如果把该元素硬编码进去,一来,降低了该事件代码的复用性,多占内存,二来,容易造成内存泄漏。

IE的事件模型到IE7仍没有改进,实在是令人很不爽。除了上面这一点外,没有capture阶段也是一个问题。

在event方面,比上面帖子提到问题更麻烦的是,在不同浏览器中,事件的含义本身不一致!!这点上,已知的类库没有一个完全解决的!!

举个例子,focus和blur事件,在w3c标准中应该是不bubble的,但是ff中是bubble的。这点上IE稍好,对许多事件它都有两套甚至更多(如关于focus的有onfocus,onblur,onfocusin,onfoucsout,onactivate,ondeactivate,onbeforeactivate,onbeforedeactivate),一套bubble一套不bubble,满足不同的需要。再如click事件和DOMActivate事件的关系等等。。。

总之要做到跨浏览器的事件处理,首先要制定一个跨浏览器的事件模型和一系列标准,这样developer才能顺顺当当的使用。仅仅把几个不同头脸的函数包装成表面一样,是远远不够的。
0 请登录后投票
   发表时间:2007-06-04  
objot中this在bubble时也是正确的,没什么问题
至于capture嘛,ie不支持,就不管它了

事件含义这个确实很讨厌,一些事件能包装一下,一些根本就不跨浏览器。这个没什么太好办法,尽量用比较兼容的事件吧....
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics