zoukankan      html  css  js  c++  java
  • 零基础AJAX入门(含Demo演示源文件)

    零基础AJAX入门(含Demo演示源文件)

    作者:一点一滴的Beer  个人主页:http://www.cnblogs.com/beer

    摘要:因为笔者的大四毕业设计是做WebGIS系统,用过Web版的Google地图人都应该深有体会,这是一种交互性很强而且很注重用户体验的一种网页,因此AJAX技术这进入此领域最基本的技能之一。这几个月来,笔者一路单人摸索过来,途经了多少昏暗迷茫的日子,最后终于从开始的甚至对ASP.NET网络编程都一无所知的小白成长到现在对AJAX技术已经有了一些整体了解的入门级小白了。以前在网上找到的资料要么就是从最的讲起(太底层了没用,干扰大家视线),要么就是直接来个应用(缺少基本介绍,初学者难以一下接受)。本文也就不来个“深入浅出”的客套了,直接来个“单刀直入”吧。本文是由一位“初学者”而写,也是为初学者而写,所以希望读过本文后,会对各位初学AJAX的同学有所帮助,还有,正因为是初学者所以难免有些疏漏,请大家不吝指正。

    说明:本文所提及程序都是基于VS2008的.NET开发平台

    AJAX简要介绍: 

    关于AJAX的发展史本文就不再重述了,有兴趣的同学可以到网上去搜索,这种你可以说我也可以说的话,应该到处都是,本文就都略去不讲了。对于AJAX的简要概述,笔者也只有一段话:

    AJAX技术是一种能够将桌面应用程序的体验效果带给Web应用程序的技术。这种体验效果主要就是页面的无刷新数据交换以及页面无刷新改变内容。AJAX技术已经是动态网页必不可少的技术了,最著名也最经典的应用就是Google主页搜索框的“搜索建议”(用户输入一个词条后,搜索框立刻出现很多相关词条提示),还有Google地图,Gmail,各种微博客,校内人人网,WebQQ等等,AJAX技术已经将很多桌面应用程序搬到Web上去了,Web的传播力量是无与伦比的,用户在有网络和浏览器的情况下可以不需要安装任何桌面软件直接访问Web应用程序来获取自己需要的信息(比如Google Map)或者达到一些基本的通讯和办公需求(如WebQQ,Google Docs)。

    好处不说了,自己去到上面说的那些网页上去体验吧。在开发过程中,如果你只是想达到目的不在乎过程,那么异步通讯是什么原理,你就可以不用看,只要知道经过哪些函数后能够传输数据,在哪些函数后可以接收数据,找到接口就足够了本文将对这些接口进行介绍。下面开始进入“单刀直入”环节。

    Ajax(AsynchronousJavaScript and XML,异步JavaScript和XML)

    A:  Aschronorous

    异步通讯,负责数据在服务器和客户端后台之间传输数据。

    J:  JavaScript

    客户端编程语言,负责客户端数据编码解码数和数据的发送和接收以及通过操作DOM来改变和更新客户端浏览器中的页面内容。

    A:  And

    这个单词大家都认识,我就不介绍了^_^。

    X:  XML

    (Extensible Markup Language)即可扩展标记语言。负责数据的编码和解码。

    下面就开始从三个重要组成来讲解AJAX技术

    一、Aschronorous异步通讯的几种框架

    1. 最基本的XmlHttpRequest

    这基本上是所以的框架的基础,即使是后面介绍的几种实现起来更加简单的框架除去华丽的外衣,内部好像都是基于它。因为是最基础也是最底层的,所以缺点也就来了,不管实现什么功能都要面临繁重的代码工作量,笔者最初用过这种框架,后来发现了后面的几种在此基础上改进的框架后,就再也没有用过此框架了。所以,在此也只作简单介绍。

    下面奉上一段客户端代码作为示例,里面有详细注释介绍(代码是很久前到网上找的,然后自己进行了一些修改并注释的,出处也忘记了,所以原创作者见谅):

     

     

    XmlHttpRequest异步通讯
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Ajax_AlertExample.aspx.cs" Inherits="ajax2" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

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

    <head runat="server">

    <title>用AJAX的XMLHTTP技术显示服务器端XML内容</title>

    </head>

    <body>

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

    <div>

    <script type="text/javascript" language="javascript">

    if(typeof($)!="function")

    {

    function $(id)

    {

    return document.getElementById(id);

    }

    }

    var http_request = false;

    function makeRequest(url)

    {

    http_request
    = false;

    if (window.XMLHttpRequest)

    {
    // Mozilla, Safari,...

    http_request
    = new XMLHttpRequest();

    if (http_request.overrideMimeType)

    {

    http_request.overrideMimeType(
    'text/xml');

    }

    }
    else if (window.ActiveXObject)

    {
    // IE

    try

    {

    http_request
    = new ActiveXObject("Msxml2.XMLHTTP");

    }
    catch (e)

    {

    try

    {

    http_request
    = new ActiveXObject("Microsoft.XMLHTTP");

    }
    catch (e) {}

    }

    }

    if (!http_request)

    {

    alert(
    'Giving up :( Cannot create an XMLHTTP instance');

    return false;

    }

    //onreadystatechange:每个状态发生改变时,都会触发这个事件处理器,通常调用一个JS函数

    http_request.onreadystatechange
    = alertContents;

    http_request.open(
    'GET', url, true);//建立对服务器的调用,第三个参数true表示是异步的

    http_request.send(
    null);//向服务器发送请求,如果是异步的,那么就立刻返回,同步的话就会等待直到接收到响应为止。

    }

    function alertContents()

    {

    if (http_request.readyState == 4) //readyState:请求的状态,共有5个状态,4表示完成。

    {

    if (http_request.status == 200)//status:服务器的HTTP状态码 200表示交易成功

    {

    var xmldoc = http_request.responseXML;

    var root_node = xmldoc.getElementsByTagName('root').item(0);

    $(
    "receive").innerHTML=root_node.firstChild.data;

    }

    else

    {

    alert(
    'There was a problem with the request.');

    }

    }

    }

    </script>

    <span style="cursor: pointer; text-decoration: underline" onclick="makeRequest('test.xml')" >

    Make a request

    </span>

    <br />

    <br />

    <br />

    <span id="receive">显示接收服务器数据</span>

    </div>

    </form>

    </body>

    </html>

    上面的例子是对服务器端的一个xml文档进行请求,所以不需要在服务器端额外加入代码,只需要将一个如下格式的test.xml文档放在服务器根目录下即可。

    <?xml version="1.0" ?>
    <root>
    I'm a test.
    </root>

    通过上面的例子可以看出,AJAX的实现过程就是客户端利用JS函数建立一个异步通讯类,然后向服务器端发起一个URL来请求数据,然后服务器端将客户端请求的XML文档发给客户端,客户端收到数据后,再进行解码提取出有用数据,并利用JS操作客户端的控件来显示出来。整个过程页面都没有进行任何刷新就更新了数据。具体效果,开发者可以自己去试试(源码见附件Demo)。

    2. ASP.NET客户端回调

    ASP.NET客户端回调(ASP.NET Client Callback)是微软在.NET环境下为开发人员提供的一种异步通讯方式,开发人员可以通过接口ICallbackEventHandler来实现客户端页面和服务器之间的异步通讯。注:在某些场合“ASP.NET客户端回调”也被称为“ASP.NET脚本回调(ASP.NET script callbacks)”

    通过XmlHttpRequest进行异步通讯时要在客户端通过JavaScript声明一个异步通讯请求对象,这个对象和浏览器内核有关,例如在IE下面是ActiveXObject("Msxml2.XMLHTTP")。而通过ICallbackEventHandler来实现异步通讯时,则要在服务器端的页面代码文件中,要让页面实现ICallbackEventHandler接口,只要在页面的继承类中加入ICallbackEventHandler类即可。

    服务器端代码示例:

    服务器端代码示例
    using System;
    using System.Web.UI;
    public partial class GetServerTime : System.Web.UI.Page, ICallbackEventHandler
    {
    protected string clientscript = string.Empty;
    protected void Page_Load(object sender, EventArgs e)
    {
    if (!IsPostBack && !IsCallback)
    {
    clientscript
    = Page.ClientScript.GetCallbackEventReference(this, "arg", "AjaxCallBackComplete", null);
    }
    }
    #region ICallbackEventHandler 成员
    private string _callback = string.Empty;
    public string GetCallbackResult()
    {
    return _callback;
    }
    public void RaiseCallbackEvent(string eventArgument)
    {
    _callback
    = eventArgument + ", server Time at " + DateTime.Now.ToString();
    }
    #endregion
    }

    客户端代码示例:

    客户端代码示例
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="GetServerTime_ICallback.aspx.cs" Inherits="GetServerTime" %>
    <%@ Register Assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    Namespace
    ="System.Web.UI" TagPrefix="asp" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
    <title>ICallback获得服务器端时间</title>
    </head>
    <script language="javascript">
    function doCallBack()
    {
    var arg="Hello~!一点一滴的 Beer";
    <%= clientscript %>
    }
    function AjaxCallBackComplete(result)
    {
    alert(result);
    }
    </script>
    <body>
    <form id="form1" runat="server">
    <a href="javascript:void(0)" onclick="doCallBack(); ">click me</a>
    </form>
    </body>
    </html>

    在页面的继承类中加入ICallbackEventHandler类之后,那么页面中就有两个函数可以直接使用了:public void RaiseCallbackEvent(string eventArgument)和public string GetCallbackResult()。

    RaiseCallbackEvent是服务器端接收客户端数据的函数,其参数eventArgument就是数据接口,用来接收客户端在请求时向服务器端发送的数据(目前为止,笔者所了解到的,这种数据格式好像仅仅限于字符串)。GetCallbackResult则返回数据,这个数据直接返回给客户端。这两个函数就是服务器端的数据通讯接口。

    服务器端的clientscript = Page.ClientScript.GetCallbackEventReference(this, "arg", "AjaxCallBackComplete", null);语句则定义用于生成客户端脚本。通过查看MSDN可以知道,第二个参数"arg"指客户端要发送的JavaScript字符串变量,这个变量在服务器端由RaiseCallbackEvent(string eventArgument)的eventArgument承接,第三个参数是客户端在服务器端完成回调后接收服务器端发来的数据并进行处理的JavaScrpipt函数。

    回调的流程如下:

    1.用户点击页面链接触发JS函数doCallBack

    2.doCallBack准备好数据放于arg变量中,并调用由服务器端生成的客户端脚本<%= clientscript %>

    3.服务器端RaiseCallbackEvent收到数据并调用相关服务器端函数进行处理并赋值给一个全局字符串变量

    4.由GetCallbackResult函数将服务器准备好的字符串数据返回到客户端

    5.客户端由GetCallbackEventReference()设置的JS函数接收来自服务器端返回的字符串数据,然后再对数据进行处理并操作页面元素对数据进行显示等等。

    以上便是ASP.NET客户端回调的完整过程。开发人员只需要让页面继承一个ICallbackEventHandler类,然后找到数据接口和函数接口就可以轻松实现异步通讯了。此方法是就是笔者今年做一个数据查询系统所选用的异步通讯方法,因为此方法流程比较清晰,而且代码量对比第一种利用XmlHttpRequest的方法也小了很多。

    3. ASP.NET AJAX—ScriptManager注册WebServices方法

    ASP.NET AJAX是最新的微软AJAX解决方案。需要在ASP页面中拖入一个ASP.NET AJAX ScriptManager控件作为页面的第一个控件。

    通过ScriptManager控件注册WebServices方法可以实现在客户端对服务器端函数进行调用并生成客户端代码,调用格式和客户端回调类似。

    具体实现步骤如下:

    3.1新建Web服务,会在根目录下生成一个SimpleService.asmx”文件 

    此文件可以将声明和实现的代码分别放在两个文件内,只需要进行定位指向即可,然后就能够调用此Web服务类了

    <%@ WebService Language="C#" CodeBehind="~/App_Code/SimpleService.cs" Class="SimpleService" %>

    当然也可以将声明和实现放在同一个文件夹内,和demo.aspx与demo.aspx.cs的关系一样,但一般建议分开放,使项目文件层次更加清晰(虽然一个”*.asmx”文件里面只能有一个WebService声明指令)。本文就以代码分开存放的结构来讲解。

    3.2Web服务建立实现的” SimpleService.cs”文件 

    此文件就是WebService在服务器端的数据处理函数。下有一例:

    using System;
    using System.Collections;
    using System.Linq;
    using System.Web;
    using System.Web.Services;
    using System.Web.Services.Protocols;
    using System.Xml.Linq;
    /// <summary>
    ///SimpleService 的摘要说明
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo
    = WsiProfiles.BasicProfile1_1)]
    //若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
    [System.Web.Script.Services.ScriptService]
    public class SimpleService : System.Web.Services.WebService {
    public SimpleService () {
    //如果使用设计的组件,请取消注释以下行
    //InitializeComponent();
    }
    [WebMethod]
    public string HelloWorld(string name) {
    return "Hello "+name;
    }
    }

    拥有[WebMethod]声明的函数HelloWorld(),其参数name接收来自客户端传来的参数,然后返回一个字符串到客户端。

    3.3 Ajax_net_Callback.aspx”文件中拖入ScriptManager控件 

    主要演示代码如下:

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Ajax_net_Callback.aspx.cs" Inherits="Ajax_net_Callback" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
    <title>Ajax_net_Callback.aspx</title>
    <script type="text/javascript">
    function Button1_onclick()
    {
    var arg=$get('Text1').value; //$get()--ASP.NET AJAX方法,用来获取控件的引用
    SimpleService.HelloWorld(arg, OnComplate, OnTimeOut, OnError);
    return true;
    }
    function OnComplate(arg)
    {
    alert(arg);
    }
    function OnTimeOut(arg)
    {
    alert(
    "TimeOut!");
    }
    function OnError(arg)
    {
    alert(
    "eRROR!");
    }
    </script>
    </head>
    <body>
    <form id="form1" runat="server">
    <div>
    <asp:ScriptManager ID="ScriptManager1" runat="server" >
    <Services>
    <asp:ServiceReference Path="~/SimpleService.asmx" />
    </Services>
    </asp:ScriptManager>
    <input id="Button1" type="button" value="button" onclick="return Button1_onclick()" />
    <input id="Text1" type="text" value="一点一滴的Beer" />
    </div>
    </form>
    </body>
    </html>

    在ScriptManager内部注册Web服务:

    <asp:ServiceReference Path="~/SimpleService.asmx" />

    这样,本来是一个服务器端由C#语言写的类可以直接在客户端通过JS以一定的方式调用了。

    3.4然后用户就可以在客户端直接调用服务器端的WebService的实现类了。 

    在按钮点击事件所触发的函数中加入对Web服务的调用:

    SimpleService.HelloWorld(arg, OnComplate, OnTimeOut, OnError);

    第一个参数是客户端要传递的JS字符串,第二个是设定客户端接收来自服务器上的Web服务返回数据的JS函数,第三个是响应超时的JS函数,第四个是通讯出错的JS函数。客户端JS函数OnComplate(arg)的参数arg就是用来承接来自Web服务的数据的。位于服务器端的WebService一般返回string型的字符串。而用户完全可以把服务器端的轻量级别的数据以XML或者JSON的格式编码成字符串,然后一并传送(这将是下一节要介绍的内容)。

    关于WebService的研究也是一个很大的课题,WebService的功能很强大,除了能返回文本字符串外还能直接返回DataTable,甚至文件流。目前笔者还没有仔细研究过,不过,返回字符串的功能已经足够一般的数据库编程了。

    对于Web服务,笔者是比较看好的,只因为笔者已经在目前做的系统中大量用了“客户端回调”的方法来实现异步通讯了,所以就没有再去更改用此方法,但是调用Web服务的编程模式的好处显而易见,在程序设计流程上比利用ICallbackEventHandler要容易得多,而且程序设计时候,完全可以按照不同的数据请求,建立不同的Web服务,放在不同的文件夹下,更容易实现模块化程序设计,当然这只是笔者深刻体会到的,Web服务还有很多其它优点,开发人员可以到网上去自己查找。

    4.其它局部刷新方法 

    以前在学习AJAX时,自己到网上找资料,好像还有种通过引用Ajax.dll或者AjaxPro.dll然后可以实现客户端调用服务器器端的函数的方法。不过,后来觉得相关资料太少,可能也不是主流吧,所以就没有深入研究下去了,有兴趣的同学们可以去研究下。

    二、JavaScript 运行在客户端的程序

    JavaScript作为客户端脚本,根据笔者Web应用程序开发的经验来看,在ASP网页开发中扮演的地位完全不亚于C#,可以说应该是等同的,一个运行于客户端一个运行于服务器端。目前笔者对这两种语言的定位就是:JavaScript运行于客户端,负责浏览器上页面的程序设计,C#运行于服务器端,负责响应客户端的请求并计算和处理数据,然后通过网络通讯技术数据的交换将服务器和客户端Web应用程序联系起来成为一个整体。

    JavaScript主要处理的事情有:

    1.客户端发起异步请求(上一节已经提到)

    2.接收来自服务器端异步发来的数据并完成解码(下一章将提到)

    3.操作页面元素(基于DOM模型),负责数据在客户端的计算和呈现

    总之,JavaScript就像“胶水”一样将异步通讯的各个过程粘合到一起。

    关于JavaScript,对于初学者,笔者有几条建议和说明:

    1).JavaScript是客户端语言,所以不要指望它有像C#那样智能的编辑环境,像VS2008能够提供语法高亮并提示一些简单的对象成员的编辑器已经就不错了。

    2).JavaScript的调试方法,可以在你想要设置断点的JS语句前面加上debugger语句,然后将页面用IE打开,在JS程序运行到debugger语句时候,便会有弹出框提示你用VS2008来对JS脚本进行调试,你可以在VS2008的调试环境中观察JS函数的临时变量以及异常状况。

    3).JavaScript是解释性语言,所以你在编写客户端代码时候,编辑器不会像提示C#那样智能报错,所以你需要一句一句仔细写,最好写一小段就运行一次,否则你一次性写入大量代码,最后在运行时出错,你很难找到错误原因的。所以调试器可以帮助你解决逻辑问题,但是语法问题还是要靠自己解决。不过,因为JS是客户端代码,所以网上的JS代码例子资源是相当丰富的,甚至你随便打开一个网页,看到里面有好的JS效果,你都可以察看其源文件看到其JS函数的。而且网上有很多开源的已经封装好的JS框架,方便你在大规模写客户端代码时引用,这些都需要开发人员去自己学习了。

    4).和其它语言一样,JavaScript的学习也是边用边学,不需要你一开始就要有很好地基础,遇到问题就可以到网上搜索相关解答,资源相当丰富。

    总述:看本文有前提就是要有一定C#和JavaScript基础,所以关于语言具体的学习内容,不是本文的重点,所以还请读者自己查询相关资料。

    三、XML通讯消息的编码

    通过对通讯过程的介绍可以知道传输的数据一般是字符串格式,如果已经将前面的内容掌握了,你就可以对任意简单字符串进行传递了,如果要传递比较复杂的数据集合就需要在此字符串的编码上大做文章了,这就是AJAX中的XML的内容了。有一个概念希望大家能够明白――字符串可以是很长串的数据。不要觉得很不可思议,要知道整个网页的页面都是靠超文本来传输的,一般进行的AJAX通讯的数据不会太大的,都可以用一个字符串进行承载,比如笔者就用一个字符串传送过50K的数据,而显然字符串承载数据的能力远不止如此。对数据编码掌握后,就可以完全异步通讯数据的规模“从一到万”的质变。

    下面将介绍几种常用的数据编码技术,用户可以根据情况任意选择一种了解和应用。


    3.1 用户自定义分隔符编码(微量级别) 

    简单的URL后面的传递:

    比如:string strEncode=”a=10&b=20&c=30”

    这样以特殊符号作为分隔符的编码方法比较适用于结构单一的数据集合,数据在客户端和服务器端的编码和解码也是最简单的,编码只需要字符串相加即可,解码只需要用split()函数(C#和JS两种语言都有此函数)按照编码的分隔符规则进行分离并提取出有用信息即可。

    总述:此方法好处是数据编码和解码很容易,坏处也显而易见,字符串所表示的数据集合结构层次不明,当数据集合稍微有点大的时候,字符串的可读性将变得很差。所以本方法只适合于传递的数据量比较少层次比较少的微量级别,比如一般传递不多于5组的层次单一的数据,如上例所示,但即使如此,也可以满足一般的开发者的需求了。

    下面再讲的JSON编码是对于轻量级别(比微量级别要复杂一些)的数据的一种编码方式,


    3.2 JSON编码技术(轻量级别) 

    关于JSON的介绍,网上有这么一段话:JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式易于人阅读和编写同时也易于机器解析和生成。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)这些特性使JSON成为理想的数据交换语言。

    关于JSON编码更详细的介绍可以到网上查找相关文档,或者直接访问其官方网站json.org

    在做以下步骤之前,请到这个地址下载json.jsJSON.CS

    http://www.json.org/json.js 作为客户端JSON编码和解码的库文件

    http://www.json.org 找到JSON for .NET的链接。作为服务器端JSON编码和解码的库文件。

    3.2.1 服务器端JSON编码和解码

    用从json.org网页中下载的“JSON.CS“文件,然后在服务器端中引用引文件,就可以在写C#函数的时候调用里面的函数了。具体如何详细应用细节,用户可以自己去试验。笔者在此只作简要介绍,笔者对”JSON.CS“文件进行了查看,发现里面函数虽然众多,但是直接给外部调用的只有两个:

    public static object JsonDecode(string json)

    public static string JsonEncode(object json)

    调用方法示例:

    //Hashtable数据表编码成json字符串

    Hashtable mySourceTotal = new Hashtable();//承载数据的哈希表。

    string strEnCode = JSON.JsonEncode((object)mySourceTotal);//编码成字符串成功了

    //json字符串解码成Hashtable数据表

    object arrayObj;

    arrayObj = new Hashtable();

    arrayObj = JSON.JsonDecode(str_QuertConditon);

    即一个是编码函数一个是解码函数:编码函数将服务器端的object对象转换成字符串对象,然后传递到客户端;解码函数将从服务器端接收到的string对象转换成object对象供服务器提取数据。其余的函数都是供这两个函数调用的。

    需要说明的是,上面所说的string类型的数据不是一般的任意字符串,而是有一些特别分隔符组成的“JSON字符串“,只有这样格式良好的string字符串才能够被此文件中的函数进行解码,而编码的作用也就是将object数据类型编码成这样的格式良好的“JSON字符串“,正因为遵守了这样的规则才使得JSON编码能够跨语言传递数据了。

    对于服务器端的object对象,通过查看“JSON.CS“源文件,发现它的编码和解码主要基于一种Hashtable或者ArrayList的数据类型,因此用户在服务器端对数据编码的时候,首先要转换成此结构的数据类型。然后再直接调用”JSON.CS“中的编码将Hashtable或者ArrayList的数据转换成JSON格式的string类型字符串。解码也是一样的,当服务器收到来自客户端的JSON格式的string类型字符串的时候,先调用”JSON.CS“中的解码函数,然后再用Hashtable或者ArrayList类型的中间变量来承接这些数据,然后就可以提取出其中有用的数据了。

    3.2.2客户端JSON编码和解码

    从json.org网页中下载的”json.js”文件,然后在客户端引用此文件,就可以在写JS函数的时候调用里面的函数了。和服务器端的”JSON.CS”相对应的,它里面虽然代码众多,但是供外界调用的也只有两个函数――一个编码函数一个解码函数:

    JSON.stringify(value, replacer, space);//后面两个参数是可选项

    JSON.parse(text, reviver);//后面的参数是可选项

    调用方法示例:

    var jsonText = JSON.stringify(formObject); //把json编码成text

    var jsonObject = JSON.parse(result);//把text解码成json

    json是JavaScript里面的一种数据格式,其地位相当于C语言中的结构体一样,是一个数据集合,用户可以通过“结构体“的点运算符直接对里面的数据进行提取和引用。

    3.2.3中文字符串的编码和解码

    服务器端“JSON.CS“中编码函数对中文有比较好的支持,可以直接将中文编码成Unicode的编码,在程序运行期间查看这些中文字符串的时候,看不到中文,但是可以看到其对应的数字编码,这个毋须担心,经过客户端的JavaScript解码函数解码后得到的json对象可以直接被识别这样的Unicode,并直接以中文呈现在页面中的。

    客户端“json.js“中对json object的中文编码则不那么“智能”了,需要另外处理才能够传递中文字符。 只需要对中文字符串进行一个escape()的JS方法转码后就可以了,如: 

    "TB_SheBeiMC_Value":escape(TB_SheBeiMC_Value),

    在服务器端和escape()转码函数相对应的反转码函数为UrlDecode(),如:

    String TB_SheBeiMC_Value = HttpContext.Current.Server.UrlDecode(hstb["TB_SheBeiMC_Value"].ToString());

    JSON编码技术要详细介绍,也要涉及比较大的篇幅,为了不使本文篇幅过大,所以在本文中只列出一个大纲并简要介绍,关于其详细内容,将在后面的博客中进行介绍。

    总述:JSON是一种比较有潜力的网页编码格式,它具有良好的可读性(结构清晰)的移植性,对比下面XML来说其编码效率比较高――即用来表示格式的字符占整体字符数目的比例比XML字符串小多了,所以对于轻量级别的字符编码是很高效实用的,而且因为JSON格式本来就是一种JavaScript对象,所以对于客户端的JavaScript语言有着天然的亲和力,很适合传递JavaScript变量。对于“轻量级”的定义,目前笔者也没有太大概念,不过笔者有一个15*150的DataTable的传输就是用的JSON进行编码解码,不知道这样的数据算轻量级还是重量级,不过可以肯定JSON完全可以满足用户的一般编码需求了。JSON编码解码流程可参考下图:

    image

    图一、JSON编码解码流程图

    3.3 XML编码技术(重量级别) 

    3.3.1 服务器端XML编码和解码

    用.NET里面的System.Xml里面相关类可以很容易实现对XML字符串的编码和解码。关于XML的解码在.NET提供了一个XmlDocument类,并提供了大量操作XML文档节点和属性的接口函数,通过这个类,用户可以很方便实现节点定位从而实现XML文档的编码和解码。对于编码XML文档,还有一个更加容易的方法,用户直接将数据字符串和XML节点字符串相加就可以得到一个XML格式的字符串了,然后就可以用于异步通讯传输了。编码(以字符累加法为例)和解码(以XmlDocument类应用)示例如下:

    服务器端XML编码解码
    #region XML字符串的编码和解码:内存中操作
    /// <summary>
    /// 将数据编码成XML格式的字符串
    /// 参数为dt,只用来提供一些数据,然后来进行编码,没有特别意义
    /// 这个对比直接调用DataTable的API转XML更具有一般性,用户可以对服务器端的任何数据进行XML编码
    /// </summary>
    /// <param name="dt"></param>
    ///<returns></returns>
    public string EncodeXmlStr(DataTable dt)
    {
    StringBuilder strHtml
    = new StringBuilder();
    strHtml.AppendLine(
    "<China>");
    //当然,你也可以通过函数来动态获取DataTable的字符名称,从而动态设置XML节点名称,今后可以自己尝试:本例主要讲如何编码数据,只以其中第一行为例
    //因为很多情况下,作为一种轻量级别的应用的时候,都是涉及一些简单的变量值的传递,所以一般XML字符串不会太麻烦:一般是"一父多子节点"的形式.
    strHtml.AppendLine("<id>" + dt.Rows[0]["id"] + "</id>");
    strHtml.AppendLine(
    "<ProvinceID>" + dt.Rows[0]["ProvinceID"] + "</ProvinceID>");
    strHtml.AppendLine(
    "<ProvinceName>" + dt.Rows[0]["ProvinceName"] + "</ProvinceName>");
    strHtml.AppendLine(
    "<id>" + dt.Rows[1]["id"] + "</id>");
    strHtml.AppendLine(
    "<ProvinceID>" + dt.Rows[1]["ProvinceID"] + "</ProvinceID>");
    strHtml.AppendLine(
    "<ProvinceName>" + dt.Rows[1]["ProvinceName"] + "</ProvinceName>");
    strHtml.AppendLine(
    "</China>");
    return strHtml.ToString();
    }
    /// <summary>
    /// 将XML格式的字符串解码,提取内容
    /// </summary>
    /// <param name="xmlstr">对数据进行编码后的字符串</param>
    /// <returns></returns>
    public string DecodeXmlStr(string xmlstr)
    {
    string strTemp;
    XmlDocument xmlDoc
    = new XmlDocument();
    xmlDoc.LoadXml(xmlstr);
    //定位方法一:Xpath定位,此方法便于直接用地址取值.写代码时候比较直观,比较推荐用此方法取数据
    strTemp = xmlDoc.SelectSingleNode("/China/ProvinceName[1]").InnerText;//具体可以参照w3cshool中的相关文档.
    //定位方法二:用XmlNodeList定位,此方法,便于进行遍历操作
    //用XmlDocument的API来进行数据节点定位和解码了.
    //本例只以返回其中一个值为例演示XML文档的定位
    XmlElement root = xmlDoc.DocumentElement;
    XmlNodeList elemList
    = root.ChildNodes;//得到XML元素的节点。
    strTemp = elemList.Item(2).InnerText;//返回第三项"provinceName"
    return strTemp;
    }
    #endregion

    具体的在服务器端如何操作和修改XML文档的详细内容,可以参考www.cnblogs.com/weekzero 作者:小气的鬼 《在C#.net中如何操作XML》

    3.3.2 客户端XML编码和解码

    详细信息可以访问w3School主页,查看里面的XML部份介绍,当然到网上搜索相关帖子也是必需的。

    下面是笔者给的客户端JS编码解码XML文档的Demo演示:

    客户端XML编码解码
    //by:一点一滴的Beer @ http://www.cnblogs.com/beer
    //JS直接用字符串累加方法进行编码--只需要加入编码信息即可
    function EncodeXmlStr()
    {
    var str="
    <?xml version=\"1.0\" encoding=\"gb2312\"?>";
    str+="
    <China>";
    str+="
    <ProvinceName>湖北省</ProvinceName>";
    str+="
    <ProvinceName>湖南省</ProvinceName>";
    str+="
    </China>";
    return str;
    }
    //by:一点一滴的Beer @ http://www.cnblogs.com/beer
    //通过"Microsoft.XMLDOM"对象和XPath来对xml对象对待定位提取值
    //具体过程和服务器端C#解码类似,故不再多述
    function DncodeXmlStr()
    {
    var result=EncodeXmlStr();
    //debugger;
    var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
    xmlDoc.loadXML(result);//从字符串中提取信息生成XML文档
    var nodeText = xmlDoc.selectSingleNode("/China/ProvinceName[1]").text;//定位XML文档中的数据值,参数为XPath字符串
    return nodeText;
    }

    由于给的代码示例已经很清楚了,所以对于客户端的XML编码和解码就不再多介绍了,更多应用请访问http://www.google.com.hk ^_^

    总述:网上的观点是XML是一种重量级别数据编码方式,它有很多优点,对中文字符串的编码和解码有比较好的支持,文档的结构性很好,不管是编码还是解码,过程都清晰明了。对比JSON来说,缺点也很显明,就是编码的效率不是太高,往往对一个字符进行编码就需要额外至少2个字符的标签来规定格式。不过即使如此,它仍然是笔者最喜欢的编码方式,对于性能要求不是太高的网页中,不管是轻量级别的应用还是重量级别的应用,笔者都将选择XML方式,因为个人感觉写代码时它比JSON要简单多了(当然这仅是一家之言了),而且大家不难发现HTML其实也只是一种拥有特别标签的XML文档而已,所以XML和HTML文档有着天然的亲和性,很适合传递一些HTML页面内容,优点多多,还要开发人员自己去发现了。

    image

    图二、XML字符编码解码流程图

    3.4传递其它非字符串内容 

    前面说的都是对一些基本数据的传输,但有时候也会遇到一些其它内容要传输,比如文件,图片资源……这是应用AJAX技术时无法避免的,所以有必要简要介绍下。

    3.4.1 XML文件

    前面介绍的数据编码技术,都是一些在内存中的操作,就是对一些临时变量的操作和运算,但有时候我们也需要对XML文件进行传送。一些不是经常变化的信息,如:网页异常记录日志,页面参数配置文件等等,平时都存放在服务器的硬盘中,在需要的时候再调用出来。

    3.4.1.1 客户端可以直接通过JavaScript代码获取服务器端目录下的xml文件

    var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
    xmlDoc.async=false;//如果不设置成异步,那么将无法向服务器端请求到此xml文档
    xmlDoc.load("data.xml");//从服务器中提取已经有的XML文件.

    当然在通过前面介绍的XmlHttpRequest也可以进行异步请求,但个人感觉不如这个方法来得直接。

    3.4.1.2 服务器端通过C#代码导入xml文件并编码成字符串再传送到客户端

    这种方法感觉是有点“曲线救国”的味道了,但也不失为一种方法。

    服务器端读取XML文件的方法如下:

    XmlDocument xmlDoc = newXmlDocument();

     xmlDoc.Load(Server.MapPath("data.xml"));

    然后下面的步骤就参考上一节介绍的XML编码了。

    3.4.2 图片文件

    3.4.2.1请求服务器硬盘上的图片文件

    通过以下JS代码就可以实现

     

     

     

     

     

    document.getElementById("ChartDiv").innerHTML="<IMG SRC='http://10.234.172.162/equipcount/chartimages/equipCount.png?"+Math.round(Math.random()*100)+"'/>";

    这种方法适用于请求一些放在服务器硬盘中不常改变的图片资源。

    2.4.2.2 请求一个由服务器动态生成的图片

    通过以下JS代码可以实现

    document.getElementById("ChartDiv").innerHTML="<IMG SRC='charting.aspx?"+Math.round(Math.random()*100)+"'/>";


    其中“charting.aspx”是服务器端的一个页面,这个页面要Response一个图片流,这个图片流就是一个储存在内存中的图片。这种情况一个典型的应用就是“统计图显示”问题,因为对于客户端的每次请求就意味着要服务器要根据不同的数据生成不同的统计图,这种动态的数据最好是放在内存中。(关于异步请求图片,后面笔者将要专门发贴进行介绍,敬请期待)。

    注意:不管是对服务器的硬盘中的图片进行请求还是对服务器内存中的图片进行请求,图片地址后面一定要加入了个随机数,否则在异步通讯情况下,即使服务器的硬盘中图片资源变化了,本地都无法同步显示的(好像它读取的是本地的缓存中的图片资源)。

    总述:不管是哪种编码访求,因为数据编码和解码是一个比较实际的一个问题,所以遇到具体的问题还需要开发人员自己多去查资料采取具体的解决方案,本文不可能涵盖所有内容,仅能作为一个引子抛砖引玉而已,更多解决方案,请访问http://www.google.com


    四、客户端JS框架介绍

    异步通讯和XML编码解码技术问题解决后,后面的就是考验程序员JavaScritp能力的时候了,页面的动态性好不好完全取决于程序员对JavaScript应用能力的高低了。

    JavaScript对数据进行解码后,然后数据就要各司其责,开始分发到浏览器上的各个控件上去进行显示。此时就需要JavaScript来动态控制浏览器客户端的显示内容了,JavaScript通过DIV+CSS来动态改变网页的外观显示,通过DOM文档对象模型来改变更新页面中的数据内容。

    笔者一般都不喜欢ASP.NET的服务器控件,第一个版本全部使用.NET服务器控件,一路修改过来后,最后一个版本已经基本完全抛弃服务器控件而使用html控件了。在进行AJAX开发的时候,服务器只作数据计算和数据传送,而不对客户端元素进行任何操作,客户端则请求和接收数据,并负责数据的展示。服务器端和客户端两种语言,各司其责,互不干涉。有些情况下即使用了服务器控件,比如asp:DropdownList,在客户端也只是用JS把它当作一个select控件来使用。

    因为JavaScript是一种解释性语言,所以个人进行大规模开发是很难的,但是现在网上有大量的客户端JS框架来供大家使用,很多都是开源的,这无疑是初学者的福音。

    目前一些流行的JavaScritp框架有:EXTJS,ACTIVEWIDGETS,DOJO,jQuery,YUI等等。具体应用和介绍用户可以到其官网上去查看。


    五、全文总结

    本文只是对AJAX作了一下说简也不简说详也不详的介绍,它会帮初学者解决一些问题,但也不要指望它能解决很多问题,我对它的定位就是“AJAX入门向导”吧。要想成为高手,并做出美观实用且用户体验良好的交互网页,还需要开发人员不断地学习并熟练掌握和应用这些技术,这也是笔者对自己的勉励吧。

    附件Demo:AjaxTest.rar

    Author:一点一滴的Beer 

    Email /Gtalk:dreamzsm@gmail.com

    From:http://www.cnblogs.com/beer 

    Notes:欢迎转贴,但请务必在页面显眼处加个链接注明出处,请尊重作者的成果^_^

  • 相关阅读:
    void及void指针含义的深刻解析
    对个人站长职业前景的探讨之路在何方?
    Swift编程语言学习4.3—— 控制语句
    二分查找
    分布式文件系统
    常见浏览器兼容性问题与解决方式
    OutputDebugString()
    眼睛的颜色
    SVM-支持向量机算法概述
    Android学习笔记(四十):Preference的使用
  • 原文地址:https://www.cnblogs.com/beer/p/1754811.html
Copyright © 2011-2022 走看看