使用 Microsoft AJAX Library 创建自定义客户端脚本

来源:百度文库 编辑:神马文学网 时间:2024/04/24 08:15:18
使用 Microsoft AJAX Library 创建自定义客户端脚本

更新:2007 年 11 月

ASP.NET 中的 AJAX 功能有助于创建客户端脚本并将其集成到 ASP.NET 应用程序中。这包括 ECMAScript (JavaScript) 的类型系统以及为现有 ECMAScript (JavaScript) 对象提供丰富的 .NET Framework 类的扩展。ASP.NET 还包括 ScriptManager 控件,此控件可用于管理这些脚本库以及应用程序中的任何自定义脚本。

本主题包含以下部分:

  • 方案

  • 使用类型系统

  • 使用 JavaScript 基类型的扩展

  • 将客户端脚本集成到 ASP.NET Web 应用程序中

 方案

当您要执行下列操作时,可以使用 Microsoft AJAX Library 的功能:

  • 向 JavaScript 代码中添加面向对象的功能,以提高代码的重用性、灵活性和可维护性。

  • 使用反射在运行时检查客户端脚本的结构和组件。

  • 使用枚举提供不同于整数的另一种易读的表示形式。

  • 使用 JavaScript 基类型的扩展缩短常规脚本任务的开发时间。

  • 使用调试扩展和跟踪功能,实现比传统 JavaScript 调试技术更快、信息更丰富的调试。

 使用类型系统

Microsoft AJAX Library 增加了一个类型系统以及一系列对 JavaScript 对象的扩展,可提供与 .NET Framework 功能类似的面向对象的常用功能。利用这些功能,可按一种结构化方式编写支持 AJAX 的 ASP.NET 应用程序,这不仅能提高可维护性,还简化了添加功能以及对功能分层的操作。Microsoft AJAX Library 扩展为 JavaScript 添加了下列功能:

  • 命名空间

  • 继承

  • 接口

  • 枚举

  • 反射

该库还提供了针对字符串和数组的 Helper 函数。

类、成员和命名空间

Microsoft AJAX Library 包括基类及其派生的对象和组件。通过所有这些类,您可以使用面向对象的编程模型来编写客户端脚本。

Type 类为 JavaScript 编程添加了命名空间、类和继承等面向对象的功能。任何使用 Type 类注册的 JavaScript 对象都会自动获得访问此功能的权限。下面的示例演示如何使用 Type 类在 JavaScript 文件中创建并注册一个命名空间和类:

JavaScript 复制代码
Type.registerNamespace("Demo");Demo.Person = function(firstName, lastName, emailAddress) {this._firstName = firstName;this._lastName = lastName;this._emailAddress = emailAddress;}Demo.Person.prototype = {getFirstName: function() {return this._firstName;},getLastName: function() {return this._lastName;},getName: function() {return this._firstName + ' ' + this._lastName;},dispose: function() {alert('bye ' + this.getName());}}Demo.Person.registerClass('Demo.Person', null, Sys.IDisposable);// Notify ScriptManager that this is the end of the script.if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

类有四种成员:字段、属性、方法和事件。字段和属性是名称/值对,用于描述类实例的特征。字段由基元类型组成,可直接进行访问,如下面的示例所示:

复制代码
myClassInstance.name="Fred"

属性可以表示任何基元类型或引用类型。属性值需通过 get 和 set 访问器方法进行访问。在 Microsoft AJAX Library 中,get 和 set 访问器都是函数。按照约定,这些函数的名称中应使用前缀“get_”或“set_”。例如,若要获取或设置属性 cancel 的值,需要调用 get_cancelset_cancel 方法。

对于在 AJAX 客户端应用程序生命周期中发生的操作,Microsoft AJAX Library 将引发相应的事件进行响应。Microsoft AJAX Library 还提供一种为 AJAX 客户端组件创建自定义事件的标准方式。有关更多信息,请参见创建自定义客户端事件AJAX 客户端生命周期事件

Microsoft AJAX Library 提供一种有助于对常用功能进行分组的命名空间注册方式。下面的示例演示如何使用 Type.registerNamespace 和 .registerClass 方法向 Demo 命名空间中添加 Person 类。

若要对 ASP.NET 网页启用 AJAX 功能,必须向该页面添加 ScriptManager 控件。呈现该页面时,将自动生成对 AJAX 客户端脚本库的相应脚本引用。下面的示例演示一个包含 ScriptManager 控件的页面。

JavaScript 复制代码

下面的示例演示如何完成以下过程:注册命名空间,创建类,然后重新注册该类。

JavaScript 复制代码
Type.registerNamespace("Demo");Demo.Person = function(firstName, lastName, emailAddress) {this._firstName = firstName;this._lastName = lastName;this._emailAddress = emailAddress;}Demo.Person.prototype = {getFirstName: function() {return this._firstName;},getLastName: function() {return this._lastName;},getName: function() {return this._firstName + ' ' + this._lastName;},dispose: function() {alert('bye ' + this.getName());}}Demo.Person.registerClass('Demo.Person', null, Sys.IDisposable);// Notify ScriptManager that this is the end of the script.if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
JavaScript 复制代码
Namespace

This example creates an instance of the Person classand puts it in the "Demo" namespace.

访问修饰符

大多数面向对象的编程语言都包括“访问修饰符”这一概念。通过访问修饰符,可以指定类或成员可用的上下文,例如是对外部程序可用,还是对同一命名空间中的内部类可用,抑或是仅在特定的代码块中可用。JavaScript 中没有访问修饰符。但是,Microsoft AJAX Library 遵循以下约定:名称以下划线字符(“_”)开头的成员视为私有成员,不能从成员所属类的外部访问它们。

继承

继承是指一个类从另一个类派生的能力。派生类可自动继承基类的所有字段、属性、方法和事件。派生类可以添加新成员或者重写基类的现有成员,以更改这些成员的行为。

下面的示例包含两个在脚本中定义的类:PersonEmployee,其中 Employee 派生自 Person。这两个类演示私有字段的用法,并且它们都具有公共属性和方法。此外,Employee 还重写 Person 类的 toString 实现并使用基类的功能。

JavaScript 复制代码
Type.registerNamespace("Demo");Demo.Person = function(firstName, lastName, emailAddress) {this._firstName = firstName;this._lastName = lastName;this._emailAddress = emailAddress;}Demo.Person.prototype = {getFirstName: function() {return this._firstName;},getLastName: function() {return this._lastName;},getEmailAddress: function() {return this._emailAddress;},setEmailAddress: function(emailAddress) {this._emailAddress = emailAddress;},getName: function() {return this._firstName + ' ' + this._lastName;},dispose: function() {alert('bye ' + this.getName());},sendMail: function() {var emailAddress = this.getEmailAddress();if (emailAddress.indexOf('@') < 0) {emailAddress = emailAddress + '@example.com';}alert('Sending mail to ' + emailAddress + ' ...');},toString: function() {return this.getName() + ' (' + this.getEmailAddress() + ')';}}Demo.Person.registerClass('Demo.Person', null, Sys.IDisposable);Demo.Employee = function(firstName, lastName, emailAddress, team, title) {Demo.Employee.initializeBase(this, [firstName, lastName, emailAddress]);this._team = team;this._title = title;}Demo.Employee.prototype = {getTeam: function() {return this._team;},setTeam: function(team) {this._team = team;},getTitle: function() {return this._title;},setTitle: function(title) {this._title = title;},toString: function() {return Demo.Employee.callBaseMethod(this, 'toString') + '\r\n' + this.getTitle() + '\r\n' + this.getTeam();}}Demo.Employee.registerClass('Demo.Employee', Demo.Person);
JavaScript 复制代码
Inheritance

Inheritance

This file contains two classes defined in script: Person and Employee, whereEmployee derives from Person.

Each class has private fields, and public properties and methods. In addition,Employee overrides the toString implementation, and in doing so, it uses thebase class functionality.

This example puts the Person class in the "Demo" namespace.

接口

接口用于定义实现它的类的输入和输出要求。这样,函数可以和实现同一接口的类进行交互,而不用考虑该类还实现哪些其他功能。

下面的示例定义一个 Tree 基类和一个 IFruitTree 接口。两个派生类 AppleBanana 可实现 IFruitTree 接口,但 Pine 类不实现该接口。实现 IFruitTree 接口的任何类都可确保 bearFruit 方法是该类的成员。

JavaScript 复制代码
Type.registerNamespace("Demo.Trees");Demo.Trees.IFruitTree = function() {}Demo.Trees.IFruitTree.Prototype = {bearFruit: function(){}}Demo.Trees.IFruitTree.registerInterface('Demo.Trees.IFruitTree');Demo.Trees.Tree = function(name) {this._name = name;}Demo.Trees.Tree.prototype = {returnName: function() {return this._name;},toStringCustom: function() {return this.returnName();},makeLeaves: function() {}}Demo.Trees.Tree.registerClass('Demo.Trees.Tree');Demo.Trees.FruitTree = function(name, description) {Demo.Trees.FruitTree.initializeBase(this, [name]);this._description = description;}Demo.Trees.FruitTree.prototype.bearFruit = function() {return this._description;}Demo.Trees.FruitTree.registerClass('Demo.Trees.FruitTree', Demo.Trees.Tree, Demo.Trees.IFruitTree);Demo.Trees.Apple = function() {Demo.Trees.Apple.initializeBase(this, ['Apple', 'red and crunchy']);}Demo.Trees.Apple.prototype = {makeLeaves: function() {alert('Medium-sized and desiduous');},toStringCustom: function() {return 'FruitTree ' + Demo.Trees.Apple.callBaseMethod(this, 'toStringCustom');}}Demo.Trees.Apple.registerClass('Demo.Trees.Apple', Demo.Trees.FruitTree);Demo.Trees.GreenApple = function() {Demo.Trees.GreenApple.initializeBase(this);// You must set the _description feild after initializeBase// or you will get the base value.this._description = 'green and sour';}Demo.Trees.GreenApple.prototype.toStringCustom = function() {return Demo.Trees.GreenApple.callBaseMethod(this, 'toStringCustom') + ' ... its GreenApple!';}Demo.Trees.GreenApple.registerClass('Demo.Trees.GreenApple', Demo.Trees.Apple);Demo.Trees.Banana = function(description) {Demo.Trees.Banana.initializeBase(this, ['Banana', 'yellow and squishy']);}Demo.Trees.Banana.prototype.makeLeaves = function() {alert('Big and green');}Demo.Trees.Banana.registerClass('Demo.Trees.Banana', Demo.Trees.FruitTree);Demo.Trees.Pine = function() {Demo.Trees.Pine.initializeBase(this, ['Pine']);}Demo.Trees.Pine.prototype.makeLeaves = function() {alert('Needles in clusters');}Demo.Trees.Pine.registerClass('Demo.Trees.Pine', Demo.Trees.Tree);
JavaScript 复制代码
Interface

Interface

This file contains a Tree base class, and an IFruitTree interface.Apple and Banana, two derived classes implement that interface, whereas,Pine does not implement that interface.

枚举

枚举是指包含一组命名整数常量的类。您可以像访问属性那样访问这些值,如下面的示例所示:

复制代码
myObject.color = myColorEnum.red

枚举提供不同于整数的另一种易读的表示形式。有关 Microsoft AJAX Library 中的枚举的更多信息,请参见 Type.registerEnum 方法 (ASP.NET AJAX)

下面的示例定义一个命名颜色的枚举,这些命名颜色用于表示十六进制的值。

JavaScript 复制代码
Type.registerNamespace("Demo");// Define an enumeration type and register it.Demo.Color = function(){};Demo.Color.prototype ={Red:    0xFF0000,Blue:   0x0000FF,Green:  0x00FF00,White:  0xFFFFFF}Demo.Color.registerEnum("Demo.Color");
JavaScript 复制代码
Enumeration

This example creates an Enumeration of colorsand applies them to page background.

反射

反射是指在运行时检查程序的结构和组件的能力。实现反射的 API 是对 Type 类的扩展。通过这些方法,可以收集有关对象的信息,例如该对象继承自谁,它是否实现特定的接口,以及它是否是特定类的实例等。

下面的示例使用反射 API 对前面接口示例中的 GreenApple 类进行测试。

JavaScript 复制代码
Reflection

This example tests the Demo.Trees.GreenApple classagainst various reflection APIs.

 使用 JavaScript 基类型的扩展

JavaScript 基类型的扩展可为这些类型提供附加功能。有关这些扩展的更多信息,请参见下列主题:

  • Array 类型扩展

  • Boolean 类型扩展

  • Date 类型扩展

  • Error 类型扩展

  • Number 类型扩展

  • Object 类型扩展

  • String 类型扩展

Sys.Debug 类可提供丰富的调试功能。有关更多信息,请参见 调试和跟踪 AJAX 应用程序概述Sys.Debug 类概述。

如果基于 Microsoft AJAX Library 创建组件,则可以创建由 ScriptManager 控件自动管理的脚本文件的调试版本和发行版本。通过在脚本文件名中添加“.debug”部分,可以标识脚本文件的调试版本。例如,下面的脚本文件名标识同一文件的零售版本和调试版本:

  • MyScript.js(零售版)

  • MyScript.debug.js(调试版)

 将客户端脚本集成到 ASP.NET Web 应用程序中

任何 ASP.NET 网页均可以通过在 " sdata="langKeyword">

但是,以此方式调用的脚本将不能参与部分页呈现,或无法访问 Microsoft AJAX Library 的某些组件。若要使脚本文件可在支持 AJAX 的 ASP.NET Web 应用程序中用于部分页呈现,必须在该页面的 ScriptManager 控件中注册该脚本。若要注册脚本文件,请创建一个指向相关文件的 ScriptReference 对象,并使之将该文件添加到 Scripts 集合中。下面的示例演示如何在标记中执行此操作:

复制代码
 

若要使脚本文件得到 ScriptManager 控件的正确处理,每个文件都必须在末尾包含对 Sys.Application.notifyScriptLoaded 方法的调用。此调用可通知应用程序,已完成文件加载。下面的示例演示用于实现此目的的代码:

复制代码
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

此外,您还可以将 .js 文件作为资源嵌入在托管代码程序集中(如果创建的 ASP.NET 服务器控件在客户端脚本中实现其 AJAX 功能,则可能需要这样做)。将脚本嵌入在程序集中时,脚本中便无需包括通知语句。此外,您也不必在脚本引用中指定 path 属性。但是,必须提供不带文件扩展名的程序集名称,如下面的示例所示:

复制代码
 
说明:

对页面开发人员而言,此情况并不常见,因为嵌有脚本库的大多数控件都会从内部引用其脚本。有关更多信息,请参见 演练:将 JavaScript 文件作为资源嵌入到程序集中

此外,通过在代码中创建脚本引用并将它们添加到 Scripts 集合中,还可以用编程方式注册脚本。有关更多信息,请参见 动态分配脚本引用

使用 ScriptManager 控件的注册方法,可以注册部分页更新所需的脚本。您可以按下列方式使用这些方法:

  • 若要在代码中生成客户端脚本,请以字符串形式生成一个脚本块,然后将其传递给 RegisterClientScriptBlock 方法。

  • 若要添加没有 Microsoft AJAX Library 依赖项的独立脚本文件,请使用 RegisterClientScriptInclude 方法。 

  • 若要添加嵌入在程序集中的脚本文件,请使用 RegisterClientScriptInclude 方法。

    说明:

    使用这些方法注册的脚本不具有本地化支持。

有关脚本注册方法的完整列表及其用法,请参见 ScriptManager 控件概述。

任何要注册的脚本块或内联脚本都必须位于页面的 " sdata="langKeyword">

元素中。否则,该脚本将不能在 ScriptManager 控件中注册,从而无法访问 ASP.NET AJAX 功能。有关更多信息,请参见 Sys.Application.initialize 方法

 请参见

任务

示例 AJAX 应用程序

概念

部分页呈现概述 ASP.NET AJAX 概述 ASP.NET 网页中的客户端脚本 创建客户端组件和控件

参考

Type