AJAX 客户端控件






4.39/5 (9投票s)
本文介绍如何使用 ASP.NET AJAX 库创建客户端控件。
引言
本文介绍了使用新的 AJAX 框架进行客户端控件开发的说明。我附上了一些使用 AJAX 库开发的客户端控件示例。本文是了解 AJAX 客户端组件开发的一个很好的起点。
背景
JavaScript 是一种面向对象的语言,但其方法与其他语言(如 C# 或 C++)截然不同。JavaScript 没有类的概念,因此对象不是类的实例。JavaScript 对象可以被视为键值对的集合。
在 JavaScript 中,对象可以通过多种方式创建。例如:
var table = new Object();
//or
var table = {};
可以向此对象添加属性。
table.Name = "Ikea Comp table";
//or
table["Name"] = "Ikea Comp table";
如果属性之前未定义,则在赋值时会创建它。
同样,可以将函数添加到上述 table
对象中。
table.GetName = function()
{
return this.Name;
}
在 JavaScript 中创建对象的另一种方法是:
//this function can be represented
//as a class with properties and functions inside it.
function Cat()
{
this.name = "kitty"
this.type = "big";
this.Details = function ()
{
alert(this.name +" " +this.type);
}
}
//This method is shared within all objects
//Prototype is used to define the template of the object and used
//to implement inheritance. Reference to objects and arrays added to
//the prototype object are shared between all the instances.
//functions defined in prototype are also shared between objects and it
//saves a little memory but are a little slow to call as compared to
//functions defined in constructor
//another way to write Cat.prototype.speak = function()....
Cat.prototype={
speak : function()
{
alert('meaaoooww');
}
}
//Static Function on Cat Object
Cat.StaicFunc = function()
{
//this.name or any other property is not accessible
//because it is a static method
alert("static function called");
}
//object of class;
var cat = new Cat();
cat.speak();
cat.Details();
Cat.StaicFunc();
Inheitance can be implemented in JavaScript as
function WildCat()
{
Cat.call(this); //Calling the base constructor
}
WildCat.prototype = new Cat();
//Overriding the base function speak
WildCat.proptotype.speak = function()
{
alert('this is wild cat..Beware');
}
创建对象的更快方法是:
var team = {name:'', members:[], count:function() { return members.length }}
上述对象是使用 JSON 格式创建的。要了解更多关于 JSON 格式的信息,请“Google”一下 :-)。
AJAX 库中的 JavaScript
ASP.NET AJAX 库扩展了 JavaScript 类型系统,以模拟 JavaScript 目前尚不具备的面向对象结构,例如接口、类和枚举。类的创建方式与 JavaScript 类似。要在 AJAX 框架中创建类:
Type.registerNamespace('Sample');
Sample.Vehicle = function ()
{
this._name;
this._type;
}
Sample.Vehicle.prototype = {
get_name : function()
{
return this._name;
},
set_name : function (value)
{
this._name = value;
},
get_type : function()
{
return this._type;
},
set_type : function(value)
{
this._type = value;
},
Honk : function()
{
alert('Loud noise coming...cant you hear that');
}
}
Sample.Vehicle.registerClass('Sample.Vehicle');
在上面的示例中,您只需调用 registerNamespace
和 registerClass
来向 AJAX 库注册您的命名空间和类。上述类有两个属性和一个函数。应使用 get_
和 set_
格式来获取和设置属性的值。
registerClass
的格式类似于:
NameofClass.registerClass('NameofClass', BaseClass, InterfacesImplemented)
接口可以定义为:
Sample.IDrive = function()
{
throw Error.notImplemented();
}
Sample.IDrive.prototype = {
Drive : function ()
{
throw Error.notImplemented();
}
}
Sample.IDrive.registerInterface('Sample.IDrive');
要从上述 Vehicle
类继承一个类并实现接口:
Sample.Honda = function()
{
Sample.Vehicle.initializeBase(this);
//if base class takes arguments in constructor
//then they can also be passed
//Sample.Vehicle.initializeBase(this, [arg1,arg2,...]);
}
Sample.Honda.prototype = {
Honk: function()
{
alert(this._name + ' honking ...');
//To call base method
//Sample.Honda.callBaseMethod(this, 'Test',[arg1,arg2,…]);
} ,
Drive : function()
{
alert('Driving...');
}
}
Sample.Honda.registerClass('Sample.Honda',Sample.Vehicle, Sample.IDrive);
要添加/移除事件,请使用 add_eventname
/remove_eventname
。例如:
Sample.List = function() {
this._items = [];
this._events = new Sys.EventHandlerList();
}
Sample.List.prototype = {
add : function(item) {
this._items.push(item);
this._raiseEvent('itemAdded', Sys.EventArgs.Empty);
},
get_events : function() {
return this._events;
},
add_itemAdded : function(handler) {
this.get_events().addHandler('itemAdded', handler);
},
remove_itemAdded : function(handler) {
this.get_events().removeHandler('itemAdded', handler);
},
_raiseEvent : function(eventName, eventArgs) {
var handler = this.get_events().getHandler(eventName);
if (handler) {
if (!eventArgs) {
eventArgs = Sys.EventArgs.Empty;
}
handler(this, eventArgs);
}
}
}
Sample.List.registerClass('Sample.List');
使用 AJAX Toolkit 创建客户端组件
要开始使用 AJAX,请安装 ASP.NET AJAX toolkit,并创建一个名为“ASP.NET AJAX Enabled Website”的模板网站。
在每个 AJAX 启用的网站中,默认页面上都会有一个 ScriptManager
控件,并且 'Web.config' 文件已配置为支持 AJAX。此 ScriptManager
控件的主要目的是将所有 AJAX 脚本传递给客户端并注册 Web 服务。此控件部署的文件可以是 AJAX toolkit 提供的脚本,也可以是您创建的任何其他脚本文件。
要部署包含 AJAX 类和代码的 JavaScript 文件,请编写:
<asp:ScriptManager ID="ScriptManager1" runat="server" >
<Scripts>
<asp:ScriptReference Path="~/TestObjects.js" />
</Scripts>
</asp:ScriptManager>
添加对 Web 服务的引用
<asp:ScriptManager ID="ScriptManager1" runat="server" >
<Services>
<asp:ServiceReference Path="~/Services/Service1.asmx" />
<asp:ServiceReference Path="~/Services/Service2.asmx" />
</Services>
</asp:ScriptManager>
只需在页面上添加此控件,它就可以声明式地或以编程方式提供脚本。
组件背景
组件是任何应用程序的构建块。它们封装了功能,并允许跨项目重用。我将讨论 AJAX toolkit 库的组件模型,并给出一个示例。AJAX 库允许使用 JavaScript 创建组件。使用 AJAX 创建组件的过程与 .NET Framework 类似。AJAX 组件继承自 Sys.Component
类。
AJAX 组件被归类为:
- 可视化组件:它们具有用户界面。它们继承自
Behavior
或Control
类。例如:Button
,或TextBox
控件在获得焦点时的行为(本文附有示例)。 - 非可视化组件:它们没有任何用户界面。它们继承自
Sys.Component
类。
上图显示了 Component
、Control
和 Behavior
之间的关系。Control
和 Behavior
之间的区别在于,Behavior
用于增强 Control
的基本功能。例如:如果一个 TextBox
被分配了一个新的 Behavior
,它仍然可以接受输入,但我们可以改变 TextBox
在获得焦点时的外观。而 Control
则是用来改变现有控件的功能的,例如:创建一个新的自动更新文本框控件。
创建组件
创建组件需要您重写 Sys.Component
基类的 Initialize
和 Dispose
方法。
Type.registerNamespace("Sample");
Sample.TestComponent = function() {
Sample.TestComponent.initializeBase(this);
}
Sample.TestComponent.prototype = {
//Overide initialize method
initialize : function() {
Sample.TestComponent.callBaseMethod(this, 'initialize');
alert("Initialize called on TestComponent");
},
//Overide dispose method
dispose : function() {
alert("Dispose called on TestComponent");
Sample.TestComponent.callBaseMethod(this, 'dispose');
},
time : function() {
var a = new Date();
alert(a.getTime());
}
}
Sample.TestComponent.registerClass('Sample.TestComponent',Sys.Component);
在 ASPX 页面上,添加:
//register pageInit function to be called on initialized stage of the page
Sys.Application.add_init(pageInit);
function pageInit() {
//creating component
//Alias of Sys.Component.create
$create(Sample.TestComponent, {'id':'testComponent1'});
}
function pageLoad() {
//find component and call its methods and properties
//$find -- Alias of Sys.Application.find
var testComponent = $find('testComponent1');
testComponent.time();
}
"Sys.Application
" 是库提供的一个运行时对象,用于管理应用程序中注册的客户端组件。"$create
" 是 Sys.Component.create
的别名。此方法在后台执行许多任务来创建一个组件。此方法必须在页面初始化阶段调用。使用 $create
在页面上创建的所有组件都成为 Sys.Application
对象的子组件。$find
是 Sys.Application.find
的别名,用于获取 Sys.Application
的子组件的引用。$get
是 Sys.UI.DomElement.getElementById
的别名,用于获取 DOM 元素的引用。
$create
的完整语法是:
$create(ComponentName, {Dictionary of properties },
{ Dictionary of events}, {Dictionary of refrences},
$get(associatedElementID));
对于组件,我们不需要 associatedElementID
,但对于 Behavior
和 Control
,这是一个必需的参数。
如果组件是 Behavior
或 Control
,那么 $create
会将其附加到元素 $get(associatedElementID)
。
$find
的完整语法是:
$find('componentId', container);
默认情况下,所有由 $create
创建的组件都成为 Sys.Application
的子组件,因此如果我们使用 $create
创建一些组件,则无需在 $find
中指定容器,因为默认搜索是在 Sys.Application
下进行的。
$create
执行的工作与以下代码行相同:
var testComponent = new Sample.TestComponent();
testComponent.set_id('testComponent');
testComponent.initialize();
Sys.Application.addComponent(testComponent);
不一定非要在 Sys.Application
下创建组件,但这是一个好习惯。组件可能很复杂,并且可以包含其他对象或子组件,因此对实例进行初始化和处置的集中式位置非常重要。当组件添加到 Sys.Application
容器中时,它会负责初始化和处置组件。它确保在页面加载发生之前初始化所有添加的组件。
我们也可以在 PageLoad
事件中创建上述组件的实例,如下所示:
function pageLoad() {
var testComponent = new Sample.TestComponent();
testComponent.time();
}
创建 Behavior
Behavior 继承自 Sys.UI.Behaviour
,而 Sys.UI.Behaviour
又继承自 Sys.Component
。Behavior 必须提供一个要关联的元素。Behavior 的构造函数接受一个元素,并将该元素传递给基类构造函数。
例如
Type.registerNamespace("Sample");
Sample.TestBehavior = function(element) {
Sample.TestBehavior.initializeBase(this,[element]);
}
Sample.TestBehavior.prototype = {
//Overide initialize method
initialize : function() {
Sample.TestBehavior.callBaseMethod(this, 'initialize');
alert("Initialize called on TestComponent");
},
//Overide dispose method
dispose : function() {
alert("Dispose called on TestComponent");
Sample.TestBehavior.callBaseMethod(this, 'dispose');
}
}
Sample.TestBehavior.registerClass('Sample.TestBehavior',Sys.UI.Behavior);
上述 Behavior 什么也不做。在调用 $create
时,必须传递一个元素实例,此 Behavior 将应用到该元素。
$create
会是这样的:
$create(BehaviorName, {Dictionary of properties },
{ Dictionary of events}, {Dictionary of refrences} ,
$get(associatedElementID));
$find
会是这样的:
var instance = $find('ElementName$BehaviorName');
创建 Control
与 Behavior
不同,Control
继承自 Sys.UI.Control
,而 Sys.UI.Control
继承自 Sys.Component
。Control 的构造函数也接受一个要关联的元素。一个元素只能关联一个 Control。
例如
Type.registerNamespace("Sample");
Sample.TestControl = function(element) {
Sample.TestControl.initializeBase(this,[element]);
}
Sample.TestControl.prototype = {
//Overide initialize method
initialize : function() {
Sample.TestControl.callBaseMethod(this, 'initialize');
alert("Initialize called on TestComponent");
},
//Overide dispose method
dispose : function() {
alert("Dispose called on TestComponent");
Sample.TestControl.callBaseMethod(this, 'dispose');
}
}
Sample.TestControl.registerClass('Sample.TestControl',Sys.UI.Control);
$create
对于 Control
和 Behavior
相同。$find
也与 Behavior
的情况相同。我们可以通过在 $find
中传递 ID 来访问 Control。Control 的 ID 不能像 Behavior 那样以编程方式设置。Sys.UI.Control
类会自动为 Control 分配一个 ID,该 ID 与关联元素的 ID 相同。因此,要通过 $find
访问 Control,请传递元素的 ID。
AJAX 启用的服务器控件
我上面解释的控件是客户端控件。这些控件需要在页面生命周期的初始化阶段创建。创建控件的过程由 $create
语句封装,但我们需要手动将 $create
语句注入页面。如果我们能自动添加这个 $create
语句,那么我们就可以拥有一个服务器控件。AJAX 服务器框架提供了脚本描述符,可用于将此语句注入页面代码。
ScriptComponentDescriptor
可用于创建非可视化组件,类似地,ScriptBehaviorDescriptor
和 ScriptControlDescriptor
可用于创建 Behavior
和 Control
。
在我的下一篇文章中,我将解释 AJAX 启用的服务器控件是如何工作的。