您的位置:首页 > 编程语言 > ASP

asp.net ajax的事件机制小议

2007-05-10 11:12 405 查看
 Asp.net Ajax提供的Sys.UI.DomEvent类,实现了跨浏览器的Dom事件操作,诸如以下几个常用的事件操作:$addHandler,$removeHandler,$addHandlers,$clearHandlers.
      举一个简单的使用示例:


<html xmlns="http://www.w3.org/1999/xhtml" >


<head runat="server">


    <title>无标题页</title>


</head>


<body>


    <form id="form1" runat="server">


        <asp:ScriptManager ID="ScriptManager1" runat="server">


        </asp:ScriptManager>


    <div>


        <input id="Button1" type="button" value="button" />


        <input id="txt1" type="text" />


    </div>


    </form>


</body>


</html>




<script type="text/javascript">





function pageLoad()

{




    $addHandler(document,
4000
"click",function(e)

{


        alert(e.clientX+":"+e.clientY);


    });


    




    $addHandler($get("Button1"),"click",function(e)

{


        alert($get("txt1").value);


        e.stopPropagation();


    });


}


</script>

      可以看见,通过$addHandler对一个DOM元素进行事件监听时,事件处理方法会传递进来一个默认的e参数,这一点和IE的全局的event对象的做法不同,而更符合标准的做法.
      注意,这个e参数就是事件对象,而且是一个跨浏览器的事件对象,它具有如:target,clientX,clientY,keyCode,type...等常用的属性.
      此外,这个DOM事件e对象,有两个比较重要的方法:preventDefault(阻止浏览器DOM元素的默认行为),stopPropagation(阻止DOM事件的冒泡传递).利用这两个方法,可以实现一些特别的需要.
      其实绝大多数的Ajax库,都提供了这样的跨浏览器事件编程接口.但是,这些事件都只是"DOM事件"!我们监听一个DOM元素,在监听方法里写处理逻辑,这很简单也很正常.但是这个情况满足不了asp.net ajax组件对象系统的需要,它需要"对象级事件"的编码接口.
      说到这里,必须提一下asp.net ajax的组件系统.和.net一样,asp.net ajax也引入了组件化编程的概念,它在扩展了javascript的一些功能和构建了一个完善的面向对象编程框架之外,另外构建了一个组件化编程的框架.这一点是asp.net ajax有别于其他ajax类库的一个最显著的地方,由于这一点,使得其他的类库像"游击队",而asp.net ajax更像"正规军".
      所谓组件化,是说asp.net ajax提供了一个基础组件类:Sys.Component,由此基础组件类扩展而出:Sys.UI.Control,Sys.UI.Behavior,Sys.Preview.Action,AjaxControlToolkit.Animation.Animation等不同概念不同功能域的控件类,又从这些控件类,派生出整个asp.net ajax的所有组件类,实现整个系统的组件化编程...有点说远了,这里只谈事件...
      组件是一个自给自足的类概念,它具有:属性,方法和事件.一个组件可以是DOM组件(如从Sys.UI.Control派生而来Sys.Preview.UI.Button),也可以是行为组件(如从Sys.UI.Behavior派生的Sys.Preview.ClickBehavior),还有可能是动画组件(如从AjaxControlToolkit.Animation.Animation派生的AjaxControlToolkit.Animation.ParentAnimation)等等.
      所谓"事件",逻辑描述就是:由一个"触因",引发一个操作.
      从这点讲,一般意义的"DOM事件",不过就是天然支持了一个html dom的事件系统,这个DOM事件系统,可以看作是一个"触因",我们实现"对象级事件",需要的不过是另外的一种"触因"罢了.下面我例举一个简单的示例,看看怎么在自定义的类之中实现"对象级事件":


<script type="text/javascript">




var MyClass = function(name)

{


    this._name = name;    


    this._nameChangedHandler = new Array();//事件处理器集合


}




    function MyClass$set_name(value)

{//当你执行set_name方法时,set_name方法就是一个"触因".        




        if(this._name != value)

{


            this._name = value;


            this._onNameChanged();//这个方法的调用,是实现自定义事件的根本.


        }


    }




    function MyClass$get_name()

{


        return this._name;


    }


    //加入name属性变化监听方法




    function MyClass$add_nameChanged(handler)

{


        Array.add(this._nameChangedHandler,handler);


    }


    //移除name属性变化监听方法




    function MyClass$remove_nameChanged(handler)

{


        Arr
dd07
ay.remove(this._nameChangedHandler,handler);


    }


    //实现name属性变化监听自事件




    function MyClass$_onNameChanged()

{


        var sf = this;




        Array.forEach(this._nameChangedHandler,function(v,i,array)

{


            v(sf,"nameChanged");//最主要的技术实现是这行代码,其实是监听方法的循环调用,"激发"了监听方法!


        });


    }




MyClass.prototype = 

{


    _name: null,


    _nameChangedHandler: null,


    set_name: MyClass$set_name,


    get_name: MyClass$get_name,


    


    _onNameChanged: MyClass$_onNameChanged,


    add_nameChanged: MyClass$add_nameChanged,


    remove_nameChanged: MyClass$remove_nameChanged


}




//监听方法1




function Fuc(sender,eventargs)

{


    //我们在事件监听方法中做一些事



    alert(sender.get_name()+":"+eventargs);


}


//监听方法2




function Fuc2(sender,eventargs)

{


    alert(sender.get_name());


}




//创建自定义类的对象实例


var a = new MyClass("fanrong");




//加入"name属性变化事件"的监听方法


a.add_nameChanged(Fuc);


a.add_nameChanged(Fuc2);




//改变下姓名属性,会激发nameChanged事件


a.set_name("chunrong");


</script>
      大家可以看到,在这个示例中,我们没有使用任何的DOM事件,但确实是演示了一个事件的监听方法的绑定和激发.
      这里揭示了3点实现自定义事件的根本原理:
1)事件监听方法,是使用一个集合来存放的.这里使用的是数组.通过数组元素的增/删,实现事件监听方法的绑定和移除;
2)"激发"事件,其实就是遍历集合中的监听方法,依次加以调用,调用的时候传入事件参数;
3)属性值变化事件激发的"触因",其实现的原理是"索引器"内部的_onXXX方法的调用,如果没有set_XXX这样的属性索引器,至少"属性值变化事件"是实现不了的,因为我们需要在改变属性值的时候,有地方给我们写调用_onXXX这样"激发"事件的代码 :)
      这个例子虽然小,但它是asp.net ajax中,整个组件系统实现"事件"的根本原理.一般,通过Sys.UI.Control派生的组件类,它们事件的"触因"是天然就有的DOM事件,而其他的组件类,实现事件的"触因"是各种各样的,但总有一个"点"是进行了"_onXXX"这样的事件激发方法的调用.
      从这些基本原理出发,微软提供了一个Sys.EventHandlerList类,如果查看它内部的代码,可以发现它提供了一个"事件对象"集合(是一个Object对象),每一个"事件对象"通过"事件名称"对应一个数组,这个数组就是"事件监听方法集合",这一点和我上面举的例子的做法是一样的.只是Sys.EventHandlerList可以为所有的事件绑定和移除对应的事件监听方法,而我举的例子里,只是简单的说明了如何为一个事件实现事件监听方法的绑定/移除和激发.
      此外,Sys.EventHandlerList并没有做"事件激发"的工作.因为"激发"事件时,需要传递具体的参数,而每一个不同的类,都有自己不同的参数需要传递,显然,这个步骤不通用,因此不能封装在Sys.EventHandlerList内中,而应该在具体编写一个类的激发事件代码时,由类开发程序员自己决定传递什么参数. 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息