您的位置:首页 > Web前端 > JavaScript

Javascript 中的事件绑定

2007-04-13 17:01 405 查看
为组件提供事件处理入口,可以极大的提高组件的封闭性,同时又能让组件很好的和外界通信。并且这也是我们已经习惯使用的一种开发模式,.NET、DHTML等都提供了一套完整的事件处理模型。下面是关于使用DHTML中事件的一个总结。

    
DHTML提供了3种事件的使用方式,它们分别是:
    
1、Inline HTML: <ELEMENT onXXX='handler'></ELEMENT>
    
这是最简单最常用的事件绑定方式,不过这里onXXX的值为handler是不太确切的说法。其实这个handler的位置可以放置任何合法的JavaScript语句,因为IE在生成DHMTL树时会为当前Element构建一个'匿名'成员方法,onXXX指向这个方法的handler。比如我们写下,<element id='elmt' onXXX='var abc =0; for ( var i=0 ; i < 100 ; i++ ) abc+=i;'></element>,实际上在DHMTL树种存在如下代码结构:

function anonymous()
{
var abc =0; for ( var i=0 ; i < 100 ; i++ ) abc+=i;
}


此时anonymous方法中的this就是elmt对象。

2、Event property: object.onXXX = handler

这个使用方法是把函数名(handler)赋予element预定义的事件属性上(onXXX)。这里需要注意两个问题:

一是,我们在使用object.onXXX = handler是需要保证object已经在页面中生成。比如我们为document.body赋予事件处理函数,我们必须保证document.body已经存在,就是说我们不能在<body>之前在的全局语句中使用document.body;

二是,handler必须是函数名,和使用方法1中的handler可以是任何JavaScript语句不同!我们最容易出错的使用是,当我们习惯了在inline html中使用<element id='elmt' onXXX = 'return false'></element>后,如果这样使用elmt.onXXX='return false;'。那么就歇菜了,不会有任何执行效果,当然IE也不报错。正确的使用是:

elmt.onXXX = function() { return false; }


3、Named Script: <SCRIPT FOR = object EVENT = onclick>

IE独家支持,没有怎么使用过,不觉得有什么特别的地方哈。如果您知道它的妙处愿闻其详。

DOM提供了两种事件处理使用,它们分别是:
    
1、attachEvent method:
    使用方法:bSuccess = object.attachEvent(sEvent, fpNotify)。解释就抄msdn了
    Parameters
       sEvent Required. String that specifies any of the standard DHTML Events. 
       fpNotify Required. Pointer that specifies the function to call when sEvent fires. 
    Return Value
         Boolean. Returns one of the following possible values:        true The function was bound successfully to the event. 
       false The function was not bound to the event. 
    DOM提供的这个事件附加方式实际上是一个集合操作,我们可以多次的向同一个事件签名上attach多个事件处理函数,比如:

window.attachEvent('onload', handler1);
window.attachEvent('onload', handler2);
window.attachEvent('onload', handler3);
window.attachEvent('onload', handlerN);


将会执行这个N个handler,但是不保证执行顺序。这里有个例外,attachEvent在document.body上attach事件'onload'没有效果,但是attch window对象的'onload'是正确的。根据页面初始化顺序来看,及document.body.attachEvent('onload', handler)返回true来看,这因该是IE的一个bug。

注意DHTML的Event Property方式和DOM的attachEvent方式的区别:

Event Property方式,当触发事件时,事件处理函数是一个无参数函数,我们只能通过event这个window的属性来读取和事件相关的信息。attachEvent方式,当事件处理函数被触发时,该函数的第一个参数arguments[0],默认是该窗口上的event。什么意思呢?不明白参看这里。  

---------------------------------------------补充的部分-----------------------------------------------------
JavaScript对象的引用
为了减少JavaScript对象的下载次数,Tasian只会在浏览器第一次请求应用时才会下载JavaScript文件。JavaScript对象只会驻留在Top级窗体,任何其它窗体需要引用到该JavaScript对象,只需要在引如下的方式进行引用就行:

需要引用的窗体Button = top.Button //参阅MscrRouter.js

而Button真正定义的JavaScript文件处于Top窗体,为了保证定义的对象格式能跨浏览器有效,Tasian使用了如下的格式进行对象定义:
//定义对象名
function MscrButton()
{
};
//定义对象的方法
MscrButton.onClick = function(strWin, strName)
{
MscrSystem.setAction(strWin, strName, "click", ""); 
};

请注意,在每个函数后面都有一个分号,这一点对于Tasian非常的重要。因为Tasian中所使用的JavaScript文件都是经过压缩的,并且将全局的JavaScript对象定义合成在一个JavaScript文件中。它的好处是减少网络流量、减少JavaScript对象对客户端资源的占用及减少对服务器请求的发送。

2. 遮罩运用
遮罩是指在一个对象上放置一个新的对象,新对象便是遮罩层。它能截获所有被遮罩对象的事件。

Tasian 所有的窗体都是在一个Iframe, 对于窗体拖动,在IE中能容易地进行事件捕捉处理,可以在非IE的浏览器中,当Mouse移到Iframe时,该 Iframe将会最先处理该事件,使得对Iframe的拖动无效。所以Tasian会在Iframe上加上一个可以关开的遮罩层DIV元素,当要进行窗体对象拖动时,该层会打开,当拖动完成后,该层会关闭。

3. 模态窗体Tasian有一个特殊的窗体,只有当它关闭时才能操作其它窗体内容。该窗体叫模态窗体。在JavaScript实现模拟窗体时,也是使用了一个DIV层,使得它始终于模态窗体的下一级,这样它就能截获所有对它父窗体的操作事件。

4. 动态事件绑定
在IE在动态事件绑定是通过attachEvent实现的,而在Mozilla系列是使用addEventListener。以下是代码摘自document.js两者的使用方法
if (top.isIE)
{
oDB.setCapture();
oDB.attachEvent("onmousemove", __resizingMe);
oDB.attachEvent("onmouseup", __endResizeMe);
}
else
{
document.captureEvents(Event.MOUSEEVENT | Event.MOUSEUP); 
document.addEventListener("mousemove", __resizingMe, false);
document.addEventListener("mouseup", __endResizeMe, false);
}

….
if (top.isIE)
{
oDB.detachEvent("onmousemove", __resizingMe);
oDB.detachEvent("onmouseup", __endResizeMe);
oDB.releaseCapture();

}
else
{
document.releaseEvents(Event.MOUSEMOVE | Event.MOUSEUP);
document.removeEventListener("mousemove", __resizingMe, false);
document.removeEventListener("mouseup", __endResizeMe, false);
}

5. Style对象
对于IE中HTML元素的Style对象其强大之处大家都了解,可是对于Mozilla中HTML的Style对象由于其相关介绍实在太少,所以大家都对它很陌生。其实Mozilla中的Style仍然很强大,IE能完成的功能,它大都能完成,只不过大家不了解罢了。比如IE中有filter属性用来设置渐近色,而Mozilla中可以用alpha实现。

以下代码摘自MscrSystem.js
if (!isIE)
{

oEnMsk.style.filter = "alpha(opacity = 35)";
oEnMsk.style.MozOpacity = 0.35;

}
else
{
var strHTML = "
strHTML += ">";

oObj.parentNode.insertAdjacentHTML("BeforeEnd", strHTML);
}

当然Mozilla的Style属性远不止如此,它还可以设置DIV的外观:圆形、郁圆形等。

-----------------------------------------------------------------增加的部分-----------------------------------
IE下与firefox下,javascript的事件绑定方法有所不同,以下是两个浏览下的区别,以鼠标点击事件为例:

在IE下,事件为onclick,绑定时为obj.attachEvent("eventName", functionName, useCapture);在此例中eventName为click,functionName为要调用的事件处理方法,比如a()。useCapture表示事件处理模式是否使用捕获模式,即从外向内的模式。那么整条语句应为obj.attachEvent("onclick", a, false); 
在firefox下,事件为click,绑定时为obj.addEventListener("eventName", functionName, useCapture);相应的语句为obj.addEventListener("click", functionName, useCapture);
在应用时,为了兼容性,可以使用以下判断来绑定事件:

 if (window.attachEvent)
 {//window下的事件绑定}
  else{//firefox下的事件绑定}

_--------------------------------------------------------j最后的补充---------------------------------------

今天暂时抛开prototype1.3.1,分享一下我的javscript事件设计心得。其实现的技术基础在于函数的本质,这在前面两篇中有详细叙述。

javascript内置的对象都有事件功能,比如button就有onclick事件,input就有onchange事件。那么如何在我们自定义的类中实现事件呢?很简单:

var myClass=Class.create();
myClass.prototype={
 show:function(){
  //statement

  onshow();
 },
 onshow:function(){}
}

这段代码其实就是实现了onshow事件,在myClass实例show的时候触发,你可以给onshow绑定一个函数,从而使用事件功能。在javascript中,内置的对象事件使用方法都是如此,其内部实现应该也是基于这样的模式。但是,这样的实现却有两个突出的问题:
1.只能绑定一个回调函数。如果要实现多绑定,必须自己写很多代码来封装要回调的函数到一个函数中。
2.不能传递参数。因为onshow只能赋给函数名,即函数体本身,并不能传递参数进去,为了传递参数,我曾写过一篇:《用外壳包装法给javascript触发器传递参数》,可见,同样需要写很多代码。

那么,这些问题怎么解决呢?javascript内置对象的事件使用我们就暂时不管,来考虑一下怎么在自己实现的类中避免如上两个问题。实现之前,先来考虑下面这个问题,或许有助于理解实现这个功能的意义:

我的页面需要用javascript进行一些初始化,但初始化必须在页面载入完成之后进行。通常我们会将代码放到html文件最下面。但此时,在页面载入完成之前,页面上的按钮点击需要调用必须经过初始化的方法,如果不作判断,那么就很容易出现脚本错误。因为还没有初始化,一个简单的想法是:用一个bool变量loaded来判断,初始为false,初始化完成后为true,那么按钮点击时遇到false就简单返回。这实现固然简单,但有可能造成用户发现点击无效,而不知其所以然。所以完善的做法应该是能捕获这个方法,将其绑定到页面载入完成事件上,当页面载入完成后自动调用。

好,现在看事件设计模式的实现代码:

var myClass=Class.create();
myClass.prototype={
 initialize:function(){
  this.initEvent=new Object();
 },
 init:function(){
  //初始化要执行的语句
  
  //下面是调用绑定的回调函数
  for(var p in this.initEvent){
   //extend是内置方法,不可作为回调关键字
   if(p=="extend")continue;
   this.initEvent[p].apply(_object,[]);
  }
 },
 attachOnInit:function(_key,_object,_method,_arguments){
  this.initEvent[_key]=createFunction(_object,_method,_arguments);
 },
}

function createFunction(_object,_method,_arguments){
 return function(){
  _method.apply(_object,_arguments);
 }
}

这段代码就实现了一个类myClass,具有init方法,触发oninit事件,使用时要想绑定一个事件,可以调用attachOnInit方法,参数的意思分别为:_key,回调参函数的唯一标识,如果重复,后者覆盖前者;_object回调函数的对象,如果是直接在script中的函数,可以传递this指针进去,即document对象;_method,要回调的函数,注意,这是一个函数名,不是字符串;_arguments,回调函数的参数数组。还有一个函数是createFunction,作用是包装一个函数,使其内置参数,这是外壳包装法那篇文章的一个通用实现。如果大家看过ajax之旅系列的前两篇文章,应该容易理解上面的代码,如果有什么问题,欢迎评论。

使用示例:

function myFunc(s){
 alert(s);
}
var myObj=new myClass();
myClass.attach("key1",this,myFunc,[123]);
myClass.init();

这就将myFunc函数绑定到myObj的init函数,执行后会弹出对话框123
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息