揭开AJAX神秘的面纱(AJAX个人学习笔记)

小亮哥60

小亮哥60

2016-02-19 11:01

下面图老师小编跟大家分享一个简单易学的揭开AJAX神秘的面纱(AJAX个人学习笔记)教程,get新技能是需要行动的,喜欢的朋友赶紧收藏起来学习下吧!

AJAX技术是多种计算机技术的结晶,它的名称来自:Asynchronism(异步)、JavaScript、And、XML这4个单词首字母,即异步JavaScript请求处理XML技术。简单的描述就是数据异步传输网页局部刷新的技术。AJAX很流行,WEB程序设计中如果不应用AJAX技术,可以说是不完善的设计。就好象黑白电视机与彩电一样,AJAX就是后者,是一种技术更新的革命!
本人学习AJAX时间并不长,仅10余天,不能说百分之百掌握,但也有所领悟。现在把自己的学习经过和体会写下来,与君共分享。
一、学习经过:
AJAX技术的文章和书籍很多,视频也不少,可以说是近两年最热的技术。但大多书籍介绍的全而不细,或是重点不突出,给人一种云山雾罩的感觉!这其中不乏清华大学等知名教授写的书。本人就有此方面的亲身体会,我先是下载了传智播客ajax视频教程,看了几节就看不下去了,后来又买了一本AJAX技术的书,很厚的一本60元人民币。也是天很热,耐心看了八天实在看不下去了,感觉AJAX技术很深奥,无法真正领会,就放弃了,去登山、游泳、下海、和美眉聊天、游戏,过起较为靡烂的幸福生活。后来,天气凉爽了,闲暇之余又想起AJAX这件事,于是就买来几瓶冰镇啤酒,几袋小食品,一袋瓜子,在家里边看边饮,好生自在!没有想到的是,这一看却是一通百通,AJAX技术就这样在一天时间里掌握了,而且还有自己对AJAX技术的独到领悟:AJAX应用很简单,完全可以不用编码或少量编码。

二、学习体会及重点
学习应用的语言和工具软件:本人是自学C#语言的,所以开发环境是NET框架下(ASP.NET),开发工具采用VS2008(VS2005也可以)。
学习重点:
AJAX控件的安装,特别是AJAX Control Toolkit部分的安装,详见我的博客日志,有较为详细的介绍,这里就不多说了,唯一提醒的是:VS2008和VS2005在AJAX控件安装和使用上有点区别,但不大!
1、AJAX控件5个基本控件的介绍
这是微软所提供的AJAX最基本的五大控件,也是最实用的。使用它,你完全可以不用编写任何代码,只是简单的设置一下相关属性,就可以实现AJAX异步数据更新的效果。这是让学习AJAX技术的人最为心动的,是一种傻瓜式的应用,效果不错。如果你想在以前编写的程序中应用AJAX技术,用这五大基本控件,可以在十几分钟内搞定。下面具体介绍一下:
(1)ScriptManager是脚本管理器,负责管理页面中的Ajax控件的有关脚本资源。在一个Web页面中只能有一个ScriptManager,在任何情况下使用ASP.NET Ajax控件必须在页面中添加一个ScriptManager。(这个控件一般不需设置,如果想了解具体属和和事件,可以查找有关资料。)
ScriptManager控件的前台代码形式如下所示:
代码如下:

asp:ScriptManager ID="asm1" runat=” server”
AuthenticationService Path="" /
ProfileService LoadProperties="" Path="" /
Scripts
asp:ScriptReference /
/Scripts
Services
asp:ServiceReference Path="" /
/Services
/asp:ScriptManager

下面重点介绍一下容易出错的一些属性和方法:
1、ScriptMode属性:指定发送模式。一个枚举属性,四个值:Auto、Debug、Release、Inherit。
Auto:默认值。即根据Web.config中retail配置节的值来决定发送脚本的模式。如果retail节点值为true,即将发布模式的脚本发送至客户端,否则发送调试版本。
Debug:当retail属性值为false时,ScriptManager控件将Debug版本的脚本发送至客户端。
Release:当retail属性值为false时,ScriptManager控件将Release版本的脚本发送至客户端。
Inherit:与Auto用法相同,但一般不用。
2、Services属性:用以指定当前页面所引用的WEB服务,使用asp:ServiceReference节点可以注册WEB服务,ScritpManage控件将为每一个注册的Web服务生成客户端代理。

(2)ScriptManagerProxy是ScriptManager的扩展,是专门为使用了母版页或用户控件的工程中使用的脚本管理器。当工程页面中已使用了ScriptManager,那么在母版页或用户控件中就可以使用一个ScriptManagerProxy来代理ScripManager的工作。属性上基本与ScriptManager控件一样。

(3)UpdatePanel是使用最广泛的Ajax控件,在页面中嵌入UpdatePanel,就可以实现页面的局部刷新。页面中可以有多个UpdatePanel,UpdataPanel之间也可以相互嵌套。(应用重点)
Updatapanel就是实现页面局部刷新的控件,UpdatePanel控件的前台代码如下所示:
代码如下:

asp:UpdatePanel runat="server" ID="udp1"
ContentTemplate //模板
内容模板 放置内容的区域
/ContentTemplate
Triggers //设置提交服务器的方式:异步或同步
asp:AsyncPostBackTrigger ControlID="" EventName="" / //指设置异步模式及controlID(引发更新的控件ID)和EventName(引发更新事件名称)
asp:PostBackTrigger ControlID="" / //指同步模式,一般不设置这个,可以不写这行代码,因为ajax实现的就是异步更新,同步就失去了意义!
/Triggers
/asp:UpdatePanel

重要属性和事件:
ChildrenAsTriggers:当UpdateMode属性值为Conditional时,设定UpdatePanel中的子控件的异步请求服务器是否会引起UpdatePanel的更新。
RenderMode:表示UpdatePanel解释至前台HTML代码样式,默认值为Block即解释为div/div,当该属性设置为Inline时,UpdatePanel被解释为span/span
Triggers:设定触发当前UpdatePanel更新的控件和事件。(这个是重点)
UpdateMode:设定当前UpdatePancl的更新模式:Always和Conditional。当设定为Always时,UpdatePanel不管当前是否存在Trigger都会更新。当设定为Conditional时,只有当前UpdatePancl设定了Trigger或ChildTrigger时,当前UpdatePanel控件才会更新或提交页面,或者当服务器端调用Update()方法时才会更新UpdatePanel.
需要特别说明的属性和事件:
Trigger属性:指示当前UpdatePanel使用的提交服务器方式,有同步提交或异步提交两种。同步提交只需要指定触发提交的控件ID,同步提交将会提交整个页面。异步提交需要设定触发异步提交的控件ID和服务器端的事件。

页面中多个UpdatePanel共存:当页面上有多个UpdatePanel共存时,需要设定页面上所有的UpdatePanel控件的UpdateMode属性为Conditional,否则只要任何一个UpdatePanel局部更新被触发,将会更新所有页面上的UpdatePanel。原因很简单,页面上所有的UpdatePanel控件的UpdateMode默认为Always。

多个UpdatePanel的嵌套使用:当多个UpdatePanel控件嵌套使用时,处于并列的UpdatePanel更新时互不影响。但当两个UpdatePanel相互嵌套时,处于内层的UpdatePanel局部更新时并不会影响到处层的UpdatePanel,但是外层的UpdatePanel局部更新时会更新所有嵌套在它内部的UpdatePanel。

(4)顾名思义UpdateProgress执行的是页面局部刷新过程中的工作。UpdateProgress可以提供一个刷新过程中用户状态的友好信息,如向客户提示“正在加载数据”等。
UpdateProgress控件前台代码非常简单,如下所示:
代码如下:

asp:UpdateProgress runat="server" ID="upg1"
ProgressTemplate //模板

div alige=”ecnter” style=”width:1100px” //以下代码是显示的信息或图片部分
img src=”image/loading.gif” align=middle /
/div
/ProgressTemplate
/asp:UpdateProgress

重点属性:
AssociatedUpdatePanelID:设定触发UpdateProgress的UpdatePanel的ID,一般用于页面中具有多个UpdatePanel的情况。
DisplayAfter:进度信息显示多少毫秒数。
DynamicLayout:布尔值属性,设定当前UpdateProgress是否动态绘制,而不是直接解释在前台。


(5)在WinForm的开发中,很多程序员都被Timer控件的功能所倾倒。Timer控件可以定期的触发一些事件,比如提交整个页面或刷新部分页面等。
Timer控件的定义相当简单,只需声明控件即可,代码如下所示:
asp:Timer runat="server" ID="timer1" Interval="1000" OnTick="timer1_Tick"/asp:Timer
重点属性:
Enabled:是否启动Timer控件,并触发Tick事件。
Interval:Timer控件触发Tick事件的间隔事件,单位ms.
Tick:Timer控件在设定Enabled属性为true时,每隔Interval属性限定的时间执行事件。

提示:一般把Timer控件放置在UpdatePanel之处,不然局部更新时又会重新设置间隔时间。前台代码:
代码如下:

asp:ScriptManager ID=”ScriptManagel” runat=”server”/asp:ScriptManager
asp:Timer ID=”Timer1” runat=”server” onTick=”Timer1_Tick” Interval=”1000”
/asp:Timer
asp:UpdatePanel runat="server" ID="udp1"
ContentTemplate
内容模板 放置内容的区域
/ContentTemplate
Triggers
asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" /
/Triggers
/asp:UpdatePanel

2、AJAX基本原理及案例代码
AJAX技术:我的理解就是JavaScritp前后台参数传递的技术,这里参数可以是参数值或数据流。学习AJAX基本原理,有助于对AJAX扩展控件的应用,是不会缺少的一部分。
下面列举两个AJAX最常用的方式,以便学习者体会AJAX应用原理。如初学者对部分代码不能理解,可以查找相关命令及资料!
应用方式一:
在日常的ASP.NET Ajax实现中,这种方式是最简单的、最常用的开发方式。这种方式典型的实现步骤如下所示:
创建XMLHttpRequest对象,请求特定的Ajax处理页面。
Ajax处理页面在Page_Load事件中,接收XMLHttpRequest对象的异步请求。
Ajax处理页面根据请求内容,做出相应的回应,回应可以采用this.Response.Write或this.Response.OutPutStream将响应文本或响应的XML Document放入Response对象的方式。
前台JavaScript脚本通过XMLHttpRequest对象的responseText或responseXml来接收服务器回应,并动态修改页面内容,从而实现Ajax异步无刷新应用。

应用方式二:
在ASP.NET 中,内置了一种非常适合Ajax开发的后台处理方式即HttpHandler类,实际上所有的HttpHandler类都实现了IHttpHandler接口,用以进行请求接收和回送响应。
IHttpHandler这个接口提供了最基本的Web请求和Web响应的封装,可以将此接口看作是Web容器提供的基本的Web实现方式的封装类。
IHttpHandler接口具有一个方法:ProcessRequest(HttpContext context),及一个布尔值属性:IsReusable。所有实现IHttpHandler接口的类都必须实现上述方法和属性,其中ProcessRequest方法用于接收和处理请求以及发送响应,而IsReusable指示其他请求是否可以使用IHttpHandler实例也就是说后继的Http请求是不是可以继续使用实现了该接口的类的实例,一般情况下设定为true。

应用一案例代码:
Default.aspx 文件代码(只有前台代码,后台无任何代码):
代码如下:

%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %

!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"
titleAjax请求页面/title
script type="text/javascript" language=javascript src="Ajax.js"
/script
/head
body
form id="form1" runat="server"
div style="text-align:center"
div style="width:320px;height:150px" style="text-align:center"
table border=0 cellpadding=0 cellspacing=0 width=300px
tr width=300px
td请输入回传至服务器的文本/td
/tr
tr
tdasp:TextBox runat="server" ID="txtCustomerInfo"/asp:TextBox/td
/tr
tr
tdinput type=button runat=server id="btnRequest" value="发送请求" onclick="startRequest(document.getElementById('txtCustomerInfo').value)" //td
/tr
tr
td服务器处理后文本显示如下/td
/tr
tr
td
div style="width:100%;background-color:Yellow;color:black;height:48px" id="divServerMsg"
/div
/td
/tr
/table
/div
/div
/form
/body
/html

Ajax.js 文件代码(createXmlHttp()函数部分很通用,可以在自己的应用程序中不用修改而直接复制):
代码如下:

var xmlHttp;

function createXmlHttp()
{
var activeKey=new Array("MSXML2.XMLHTTP.5.0",
"MSXML2.XMLHTTP.4.0",
"MSXML2.XMLHTTP.3.0",
"MSXML2.XMLHTTP",
"Microsoft.XMLHTTP");
if(window.ActiveXObject)
{
for(var i=0;iactiveKey.length;i++)
{
try
{
xmlHttp=new ActiveXObject(activeKey[i]);
if(xmlHttp!=null)
return xmlHttp;
}
catch(error)
{
continue;
}
}
throw new Error("客户端浏览器版本过低,不支持XMLHttpRequest对象,请更新浏览器");
}
else if(window.XMLHttpRequest)
{
xmlHttp=new window.XMLHttpRequest();
}
}

function addUrlParameter(url,parameterName,parameterValue)
{
url+=(url.indexOf("?"))==-1 ? "?" : "&";//判断当前URL中是否存在? 即参数分隔符
url+=encodeURIComponent(parameterName)+"="+encodeURIComponent(parameterValue);
return url;
}


function startRequest(customerStr)
{
xmlHttp=createXmlHttp();
xmlHttp.onreadystatechange=readyStateChangeHandler;
xmlHttp.open("GET",addUrlParameter("AjaxPage.aspx","customerInfo",customerStr),null);
xmlHttp.send(null);
}

function readyStateChangeHandler()
{
if(xmlHttp.readyState==4)
{
if(xmlHttp.status==200)
{
var str=xmlHttp.responseText;
var div=document.getElementById("divServerMsg");
div.innerHTML="b"+str+"/b";
}
}
}

AjaxPage.aspx 文件代码(前台):
代码如下:

%@ Page Language="C#" AutoEventWireup="true" CodeFile="AjaxPage.aspx.cs" Inherits="AjaxPage" %

!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无标题页/title
/head
body
form id="form1" runat="server"
div

/div
/form
/body
/html

AjaxPage.aspx.cs 文件代码(后台):
代码如下:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class AjaxPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string str = this.Request["customerInfo"].ToString();
string msg = "服务器获得你的消息,时间:" + DateTime.Now.ToShortTimeString() + "br你的消息为:" + str + "br你的地址:" + this.Request.UserHostAddress;
this.Response.Write(msg);
this.Response.End();
}
}


应用二案例代码:
Default.aspx 文件代码(同样只有前台代码,后台无任何代码):
代码如下:

%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %

!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 id="Head1" runat="server"
titleAjax请求页面/title
script type="text/javascript" language=javascript src="Ajax.js"
/script
/head
body
form id="form1" runat="server"
div style="text-align:center"
div style="width:320px;height:150px" style="text-align:center"
table border=0 cellpadding=0 cellspacing=0 width=300px
tr width=300px
td请输入回传至服务器的文本/td
/tr
tr
tdasp:TextBox runat="server" ID="txtCustomerInfo"/asp:TextBox/td
/tr
tr
tdinput type=button runat=server id="btnRequest" value="发送请求" onclick="startRequest(document.getElementById('txtCustomerInfo').value)" //td
/tr
tr
td服务器处理后文本显示如下/td
/tr
tr
td
div style="width:100%;background-color:Yellow;color:black;height:48px" id="divServerMsg"
/div
/td
/tr
/table
/div
/div
/form
/body
/html

Ajax.js 文件代码:
代码如下:

var xmlHttp;

function createXmlHttp()
{
var activeKey=new Array("MSXML2.XMLHTTP.5.0",
"MSXML2.XMLHTTP.4.0",
"MSXML2.XMLHTTP.3.0",
"MSXML2.XMLHTTP",
"Microsoft.XMLHTTP");
if(window.ActiveXObject)
{
for(var i=0;iactiveKey.length;i++)
{
try
{
xmlHttp=new ActiveXObject(activeKey[i]);
if(xmlHttp!=null)
return xmlHttp;
}
catch(error)
{
continue;
}
}
throw new Error("客户端浏览器版本过低,不支持XMLHttpRequest对象,请更新浏览器");
}
else if(window.XMLHttpRequest)
{
xmlHttp=new window.XMLHttpRequest();
}
}

function addUrlParameter(url,parameterName,parameterValue)
{
url+=(url.indexOf("?"))==-1 ? "?" : "&";//判断当前URL中是否存在? 即参数分隔符
url+=encodeURIComponent(parameterName)+"="+encodeURIComponent(parameterValue);
return url;
}


function startRequest(customerStr)
{
xmlHttp=createXmlHttp();
xmlHttp.onreadystatechange=readyStateChangeHandler;
xmlHttp.open("GET",addUrlParameter("AjaxHandler.ashx","customerInfo",customerStr),null);
xmlHttp.send(null);
}

function readyStateChangeHandler()
{
if(xmlHttp.readyState==4)
{
if(xmlHttp.status==200)
{
var str=xmlHttp.responseText;
var div=document.getElementById("divServerMsg");
div.innerHTML="b"+str+"/b";
}
}
}

AjaxHandler.ashx 文件代码(ashx扩展名属于自定义的,在新建时选择添加新项中的一般处理程序):
代码如下:

%@ WebHandler Language="C#" Class="AjaxHandler" %
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class AjaxHandler: IHttpHandler
{
public void ProcessRequest(System.Web.HttpContext context)
{
string str = context.Request["customerInfo"].ToString();
string msg = "服务器获得你的消息,时间:" + DateTime.Now.ToShortTimeString() + "br你的消息为:" + str + "br你的地址:" + context.Request.UserHostAddress;
context.Response.Write(msg);
context.Response.End();
}

public bool IsReusable
{
get
{
return true;
}
}
}

3、ASP.NET AJAX Control Toolkit 扩展控件的应用
Ajax扩展控件在VS2800中就有,但需要安装一下。具体安装方法见相关文章(我的博客中就有)。下面介绍其中两个最让人心动的控件:AutoCompleteExtender控件(文本框自动下拉列表查找控件)和CalendarExtender控件(选择日期控件)

AutoCompleteExtender控件的使用:
   使用AutoCompleteExtender控件为了实现自动完成功能及动态绑定数据,例如谷歌或百度搜索栏自动查找列表效果。在后台绑定数据库中相应的数据,如输入拼音或输简称后即可自动查找全称,鼠标点选实现快速录入。
使用步骤如下:
  第一步:在input.aspx窗体中添加一个TextBox控件,取名txtdep,添加扩展程序并选取AutoCompleteExtender控件。
  拖进设计界面后代码如下所示:
代码如下:

asp:TextBox ID="txtdep" runat="server" /asp:TextBox
cc1:AutoCompleteExtender ID="txtdep_AutoCompleteExtender" runat="server" EnableCaching="true" DelimiterCharacters="" Enabled="True" ServicePath=" " TargetControlID="txtdep" /cc1:AutoCompleteExtender
  
第二步:在Web.config文件中appSettings节添加数据库连接字符串,为连接数据库做准备:
代码如下:

appSettings
 add key="ConnString" value="server=(local);uid=sa;pwd=;persist security info=False;initial catalog= demo;Max Pool Size=1000"/
/appSettings

其中,server为SQL服务器名称,案例为本地,uid、pwd为SQL Server用户名和密码,initial catalog为要连接的数据库,,请根据实际情况填写。
  第三步:建立Web服务(WebService)。要使用AutoCompleteExtender,我们要通过Web服务传递数据。在解决方案资源管理器单击项目-〉添加新项-〉Web服务。这里使用了默认的名称WebService.asmx。
 WebService.asmx的代码修改如下:
代码如下:

using System.Collections;
using System.Web;
using System.Web.Services;
using System.Collections.Generic;
using System.Web.Services.Protocols;
using System.Data;
using System.Data.SqlClient;
using AjaxControlToolkit;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
//

若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
[System.Web.Script.Services.ScriptService]//
必需,告诉.net runtime该WebService被允许从客户端调用
代码如下:

public class WebService : System.Web.Services.WebService
 {
    public WebService () {     }
     //构建Web服务的函数
  [WebMethod]
    public string[] getdepalist(string prefixText,int count)
{
//连接数据库
        string sqlstr = System.Configuration.ConfigurationSettings.AppSettings["ConnString"];
        SqlConnection sqlcon=new SqlConnection(sqlstr);
//从数据库中的表里用select语句返回查找结果
        string mysql = "select Area_Full from ST_Area where Area_Full like" + "'" + prefixText + "%' or Area_Spell like" + "'" + prefixText + "%'" ;
//使用SqlDataAdapter对控件进行数据的填充
        SqlDataAdapter da= new SqlDataAdapter(mysql, sqlcon);
        DataSet ds=new DataSet();
        if (count == 0)
        { count = 10;}
        da.Fill(ds, "Depa_Full");
//List是一个集合,根据特殊条件找到我们所需要的值
        Liststring items = new Liststring(count);
        for (int i = 1; i = ds.Tables["Depa_Full"].Rows.Count; i++)
        {
            items.Add(ds.Tables["Depa_Full"].Rows[i - 1][0].ToString().Trim());                  
        }
        return items.ToArray();
}
}

 第四步:设置AutoCompleteExtender控件,具体设置代码如下:
代码如下:

ajaxToolkit:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server"
        TargetControlID="TextBox1"
        ServicePath="WebService.asmx"
        ServiceMethod="getdepalist "
MinimumPrefixLength="0"
/ajaxToolkit:AutoCompleteExtender

  其中,ServicePath是指Web服务的文件名。ServiceMethod是指调用Web服务的函数名。MinimumPrefixLength是指输入多少个字符后开始列出输入提示列表。

CalendarExtender控件使用:
CalendarExtender控件的使用非常简单:
  在Web窗体中添加ScriptManager控件,添加textbox,取名txtreptime,点击“添加扩展程序”,在弹出的“扩展程序向导”对话框中选择CalendarExtender控件,即可。Web窗体源页面相应代码为:
代码如下:

divasp:ScriptManager ID="ScriptManager1" runat="server"
EnableScriptGlobalization="true"
/asp:ScriptManager/div
asp:TextBox ID="txtreptime" runat="server"/asp:TextBox
                cc1:CalendarExtender ID="txtreptime_CalendarExtender" runat="server"                     Enabled="True"
 Format="yyyy-MM-dd"
 TargetControlID="txtreptime" /cc1:CalendarExtender

其中,EnableScriptGlobalization="true"自加,使控件显示中文;Format="yyyy-MM-dd"自加,控制时间的格式。

以上是对两个扩展控件的案例的介绍,希望大家举一反三,更好的在实践中应用!

作者:星光科技 时间:2009年9月17日
注:写这个学习笔记,只是记载一下自己的学习经过和体会,把一些学习重点记录下来,以备今后的巩固复习及应用,很多知识点没有详细介绍,所以并不完全适用于初学者,如果你是初学者,最好选择一本AJAX学习的书籍,然后与这篇学习笔记对照学习,效果会更好。
AJAX技术是多种计算机技术的结晶,它的名称来自:Asynchronism(异步)、JavaScript、And、XML这4个单词首字母,即异步JavaScript请求处理XML技术。简单的描述就是数据异步传输网页局部刷新的技术。AJAX很流行,WEB程序设计中如果不应用AJAX技术,可以说是不完善的设计。就好象黑白电视机与彩电一样,AJAX就是后者,是一种技术更新的革命!
本人学习AJAX时间并不长,仅10余天,不能说百分之百掌握,但也有所领悟。现在把自己的学习经过和体会写下来,与君共分享。
一、学习经过:
AJAX技术的文章和书籍很多,视频也不少,可以说是近两年最热的技术。但大多书籍介绍的全而不细,或是重点不突出,给人一种云山雾罩的感觉!这其中不乏清华大学等知名教授写的书。本人就有此方面的亲身体会,我先是下载了传智播客ajax视频教程,看了几节就看不下去了,后来又买了一本AJAX技术的书,很厚的一本60元人民币。也是天很热,耐心看了八天实在看不下去了,感觉AJAX技术很深奥,无法真正领会,就放弃了,去登山、游泳、下海、和美眉聊天、游戏,过起较为靡烂的幸福生活。后来,天气凉爽了,闲暇之余又想起AJAX这件事,于是就买来几瓶冰镇啤酒,几袋小食品,一袋瓜子,在家里边看边饮,好生自在!没有想到的是,这一看却是一通百通,AJAX技术就这样在一天时间里掌握了,而且还有自己对AJAX技术的独到领悟:AJAX应用很简单,完全可以不用编码或少量编码。

二、学习体会及重点
学习应用的语言和工具软件:本人是自学C#语言的,所以开发环境是NET框架下(ASP.NET),开发工具采用VS2008(VS2005也可以)。
学习重点:
AJAX控件的安装,特别是AJAX Control Toolkit部分的安装,详见我的博客日志,有较为详细的介绍,这里就不多说了,唯一提醒的是:VS2008和VS2005在AJAX控件安装和使用上有点区别,但不大!
AJAX控件5个基本控件的介绍
这是微软所提供的AJAX最基本的五大控件,也是最实用的。使用它,你完全可以不用编写任何代码,只是简单的设置一下相关属性,就可以实现AJAX异步数据更新的效果。这是让学习AJAX技术的人最为心动的,是一种傻瓜式的应用,效果不错。如果你想在以前编写的程序中应用AJAX技术,用这五大基本控件,可以在十几分钟内搞定。下面具体介绍一下:
(1)ScriptManager是脚本管理器,负责管理页面中的Ajax控件的有关脚本资源。在一个Web页面中只能有一个ScriptManager,在任何情况下使用ASP.NET Ajax控件必须在页面中添加一个ScriptManager。(这个控件一般不需设置,如果想了解具体属和和事件,可以查找有关资料。)
ScriptManager控件的前台代码形式如下所示:
代码如下:

asp:ScriptManager ID="asm1" runat=” server”
AuthenticationService Path="" /
ProfileService LoadProperties="" Path="" /
Scripts
asp:ScriptReference /
/Scripts
Services
asp:ServiceReference Path="" /
/Services
/asp:ScriptManager

下面重点介绍一下容易出错的一些属性和方法:
1、ScriptMode属性:指定发送模式。一个枚举属性,四个值:Auto、Debug、Release、Inherit。
Auto:默认值。即根据Web.config中retail配置节的值来决定发送脚本的模式。如果retail节点值为true,即将发布模式的脚本发送至客户端,否则发送调试版本。
Debug:当retail属性值为false时,ScriptManager控件将Debug版本的脚本发送至客户端。
Release:当retail属性值为false时,ScriptManager控件将Release版本的脚本发送至客户端。
Inherit:与Auto用法相同,但一般不用。
2、Services属性:用以指定当前页面所引用的WEB服务,使用asp:ServiceReference节点可以注册WEB服务,ScritpManage控件将为每一个注册的Web服务生成客户端代理。

(2)ScriptManagerProxy是ScriptManager的扩展,是专门为使用了母版页或用户控件的工程中使用的脚本管理器。当工程页面中已使用了ScriptManager,那么在母版页或用户控件中就可以使用一个ScriptManagerProxy来代理ScripManager的工作。属性上基本与ScriptManager控件一样。

(3)UpdatePanel是使用最广泛的Ajax控件,在页面中嵌入UpdatePanel,就可以实现页面的局部刷新。页面中可以有多个UpdatePanel,UpdataPanel之间也可以相互嵌套。(应用重点)
Updatapanel就是实现页面局部刷新的控件,UpdatePanel控件的前台代码如下所示:
代码如下:

asp:UpdatePanel runat="server" ID="udp1"
ContentTemplate //模板
内容模板 放置内容的区域
/ContentTemplate
Triggers //设置提交服务器的方式:异步或同步
asp:AsyncPostBackTrigger ControlID="" EventName="" / //指设置异步模式及controlID(引发更新的控件ID)和EventName(引发更新事件名称)
asp:PostBackTrigger ControlID="" / //指同步模式,一般不设置这个,可以不写这行代码,因为ajax实现的就是异步更新,同步就失去了意义!
/Triggers
/asp:UpdatePanel

重要属性和事件:
ChildrenAsTriggers:当UpdateMode属性值为Conditional时,设定UpdatePanel中的子控件的异步请求服务器是否会引起UpdatePanel的更新。
RenderMode:表示UpdatePanel解释至前台HTML代码样式,默认值为Block即解释为div/div,当该属性设置为Inline时,UpdatePanel被解释为span/span
Triggers:设定触发当前UpdatePanel更新的控件和事件。(这个是重点)
UpdateMode:设定当前UpdatePancl的更新模式:Always和Conditional。当设定为Always时,UpdatePanel不管当前是否存在Trigger都会更新。当设定为Conditional时,只有当前UpdatePancl设定了Trigger或ChildTrigger时,当前UpdatePanel控件才会更新或提交页面,或者当服务器端调用Update()方法时才会更新UpdatePanel.
需要特别说明的属性和事件:
Trigger属性:指示当前UpdatePanel使用的提交服务器方式,有同步提交或异步提交两种。同步提交只需要指定触发提交的控件ID,同步提交将会提交整个页面。异步提交需要设定触发异步提交的控件ID和服务器端的事件。

页面中多个UpdatePanel共存:当页面上有多个UpdatePanel共存时,需要设定页面上所有的UpdatePanel控件的UpdateMode属性为Conditional,否则只要任何一个UpdatePanel局部更新被触发,将会更新所有页面上的UpdatePanel。原因很简单,页面上所有的UpdatePanel控件的UpdateMode默认为Always。

多个UpdatePanel的嵌套使用:当多个UpdatePanel控件嵌套使用时,处于并列的UpdatePanel更新时互不影响。但当两个UpdatePanel相互嵌套时,处于内层的UpdatePanel局部更新时并不会影响到处层的UpdatePanel,但是外层的UpdatePanel局部更新时会更新所有嵌套在它内部的UpdatePanel。

(4)顾名思义UpdateProgress执行的是页面局部刷新过程中的工作。UpdateProgress可以提供一个刷新过程中用户状态的友好信息,如向客户提示“正在加载数据”等。
UpdateProgress控件前台代码非常简单,如下所示:
代码如下:

asp:UpdateProgress runat="server" ID="upg1"
ProgressTemplate //模板

div alige=”ecnter” style=”width:1100px” //以下代码是显示的信息或图片部分
img src=”image/loading.gif” align=middle /
/div
/ProgressTemplate
/asp:UpdateProgress

重点属性:
AssociatedUpdatePanelID:设定触发UpdateProgress的UpdatePanel的ID,一般用于页面中具有多个UpdatePanel的情况。
DisplayAfter:进度信息显示多少毫秒数。
DynamicLayout:布尔值属性,设定当前UpdateProgress是否动态绘制,而不是直接解释在前台。


(5)在WinForm的开发中,很多程序员都被Timer控件的功能所倾倒。Timer控件可以定期的触发一些事件,比如提交整个页面或刷新部分页面等。
Timer控件的定义相当简单,只需声明控件即可,代码如下所示:
asp:Timer runat="server" ID="timer1" Interval="1000" OnTick="timer1_Tick"/asp:Timer
重点属性:
Enabled:是否启动Timer控件,并触发Tick事件。
Interval:Timer控件触发Tick事件的间隔事件,单位ms.
Tick:Timer控件在设定Enabled属性为true时,每隔Interval属性限定的时间执行事件。

提示:一般把Timer控件放置在UpdatePanel之处,不然局部更新时又会重新设置间隔时间。前台代码:
代码如下:

asp:ScriptManager ID=”ScriptManagel” runat=”server”/asp:ScriptManager
asp:Timer ID=”Timer1” runat=”server” onTick=”Timer1_Tick” Interval=”1000”
/asp:Timer
asp:UpdatePanel runat="server" ID="udp1"
ContentTemplate
内容模板 放置内容的区域
/ContentTemplate
Triggers
asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" /
/Triggers
/asp:UpdatePanel


3、AJAX基本原理及案例代码
AJAX技术:我的理解就是JavaScritp前后台参数传递的技术,这里参数可以是参数值或数据流。学习AJAX基本原理,有助于对AJAX扩展控件的应用,是不可缺少的一部分。
下面列举两个AJAX最常用的方式,以便学习者体会AJAX应用原理。如初学者对部分代码不能理解,可以查找相关命令及资料!
应用方式一:
在日常的ASP.NET Ajax实现中,这种方式是最简单的、最常用的开发方式。这种方式典型的实现步骤如下所示:
创建XMLHttpRequest对象,请求特定的Ajax处理页面。
Ajax处理页面在Page_Load事件中,接收XMLHttpRequest对象的异步请求。
Ajax处理页面根据请求内容,做出相应的回应,回应可以采用this.Response.Write或this.Response.OutPutStream将响应文本或响应的XML Document放入Response对象的方式。
前台JavaScript脚本通过XMLHttpRequest对象的responseText或responseXml来接收服务器回应,并动态修改页面内容,从而实现Ajax异步无刷新应用。

应用方式二:
在ASP.NET 中,内置了一种非常适合Ajax开发的后台处理方式即HttpHandler类,实际上所有的HttpHandler类都实现了IHttpHandler接口,用以进行请求接收和回送响应。
IHttpHandler这个接口提供了最基本的Web请求和Web响应的封装,可以将此接口看作是Web容器提供的基本的Web实现方式的封装类。
IHttpHandler接口具有一个方法:ProcessRequest(HttpContext context),及一个布尔值属性:IsReusable。所有实现IHttpHandler接口的类都必须实现上述方法和属性,其中ProcessRequest方法用于接收和处理请求以及发送响应,而IsReusable指示其他请求是否可以使用IHttpHandler实例也就是说后继的Http请求是不是可以继续使用实现了该接口的类的实例,一般情况下设定为true。

应用一案例代码:
Default.aspx 文件代码(只有前台代码,后台无任何代码):
代码如下:

%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %

!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"
titleAjax请求页面/title
script type="text/javascript" language=javascript src="Ajax.js"
/script
/head
body
form id="form1" runat="server"
div style="text-align:center"
div style="width:320px;height:150px" style="text-align:center"
table border=0 cellpadding=0 cellspacing=0 width=300px
tr width=300px
td请输入回传至服务器的文本/td
/tr
tr
tdasp:TextBox runat="server" ID="txtCustomerInfo"/asp:TextBox/td
/tr
tr
tdinput type=button runat=server id="btnRequest" value="发送请求" onclick="startRequest(document.getElementById('txtCustomerInfo').value)" //td
/tr
tr
td服务器处理后文本显示如下/td
/tr
tr
td
div style="width:100%;background-color:Yellow;color:black;height:48px" id="divServerMsg"
/div
/td
/tr
/table
/div
/div
/form
/body
/html

Ajax.js 文件代码(createXmlHttp()函数部分很通用,可以在自己的应用程序中不用修改而直接复制):
代码如下:

var xmlHttp;

function createXmlHttp()
{
var activeKey=new Array("MSXML2.XMLHTTP.5.0",
"MSXML2.XMLHTTP.4.0",
"MSXML2.XMLHTTP.3.0",
"MSXML2.XMLHTTP",
"Microsoft.XMLHTTP");
if(window.ActiveXObject)
{
for(var i=0;iactiveKey.length;i++)
{
try
{
xmlHttp=new ActiveXObject(activeKey[i]);
if(xmlHttp!=null)
return xmlHttp;
}
catch(error)
{
continue;
}
}
throw new Error("客户端浏览器版本过低,不支持XMLHttpRequest对象,请更新浏览器");
}
else if(window.XMLHttpRequest)
{
xmlHttp=new window.XMLHttpRequest();
}
}

function addUrlParameter(url,parameterName,parameterValue)
{
url+=(url.indexOf("?"))==-1 ? "?" : "&";//判断当前URL中是否存在? 即参数分隔符
url+=encodeURIComponent(parameterName)+"="+encodeURIComponent(parameterValue);
return url;
}


function startRequest(customerStr)
{
xmlHttp=createXmlHttp();
xmlHttp.onreadystatechange=readyStateChangeHandler;
xmlHttp.open("GET",addUrlParameter("AjaxPage.aspx","customerInfo",customerStr),null);
xmlHttp.send(null);
}

function readyStateChangeHandler()
{
if(xmlHttp.readyState==4)
{
if(xmlHttp.status==200)
{
var str=xmlHttp.responseText;
var div=document.getElementById("divServerMsg");
div.innerHTML="b"+str+"/b";
}
}
}

AjaxPage.aspx 文件代码(前台):
代码如下:

%@ Page Language="C#" AutoEventWireup="true" CodeFile="AjaxPage.aspx.cs" Inherits="AjaxPage" %

!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无标题页/title
/head
body
form id="form1" runat="server"
div

/div
/form
/body
/html

AjaxPage.aspx.cs 文件代码(后台):
代码如下:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class AjaxPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string str = this.Request["customerInfo"].ToString();
string msg = "服务器获得你的消息,时间:" + DateTime.Now.ToShortTimeString() + "br你的消息为:" + str + "br你的地址:" + this.Request.UserHostAddress;
this.Response.Write(msg);
this.Response.End();
}
}


应用二案例代码:
Default.aspx 文件代码(同样只有前台代码,后台无任何代码):
代码如下:

%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %

!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 id="Head1" runat="server"
titleAjax请求页面/title
script type="text/javascript" language=javascript src="Ajax.js"
/script
/head
body
form id="form1" runat="server"
div style="text-align:center"
div style="width:320px;height:150px" style="text-align:center"
table border=0 cellpadding=0 cellspacing=0 width=300px
tr width=300px
td请输入回传至服务器的文本/td
/tr
tr
tdasp:TextBox runat="server" ID="txtCustomerInfo"/asp:TextBox/td
/tr
tr
tdinput type=button runat=server id="btnRequest" value="发送请求" onclick="startRequest(document.getElementById('txtCustomerInfo').value)" //td
/tr
tr
td服务器处理后文本显示如下/td
/tr
tr
td
div style="width:100%;background-color:Yellow;color:black;height:48px" id="divServerMsg"
/div
/td
/tr
/table
/div
/div
/form
/body
/html

Ajax.js 文件代码:
代码如下:

var xmlHttp;

function createXmlHttp()
{
var activeKey=new Array("MSXML2.XMLHTTP.5.0",
"MSXML2.XMLHTTP.4.0",
"MSXML2.XMLHTTP.3.0",
"MSXML2.XMLHTTP",
"Microsoft.XMLHTTP");
if(window.ActiveXObject)
{
for(var i=0;iactiveKey.length;i++)
{
try
{
xmlHttp=new ActiveXObject(activeKey[i]);
if(xmlHttp!=null)
return xmlHttp;
}
catch(error)
{
continue;
}
}
throw new Error("客户端浏览器版本过低,不支持XMLHttpRequest对象,请更新浏览器");
}
else if(window.XMLHttpRequest)
{
xmlHttp=new window.XMLHttpRequest();
}
}

function addUrlParameter(url,parameterName,parameterValue)
{
url+=(url.indexOf("?"))==-1 ? "?" : "&";//判断当前URL中是否存在? 即参数分隔符
url+=encodeURIComponent(parameterName)+"="+encodeURIComponent(parameterValue);
return url;
}


function startRequest(customerStr)
{
xmlHttp=createXmlHttp();
xmlHttp.onreadystatechange=readyStateChangeHandler;
xmlHttp.open("GET",addUrlParameter("AjaxHandler.ashx","customerInfo",customerStr),null);
xmlHttp.send(null);
}

function readyStateChangeHandler()
{
if(xmlHttp.readyState==4)
{
if(xmlHttp.status==200)
{
var str=xmlHttp.responseText;
var div=document.getElementById("divServerMsg");
div.innerHTML="b"+str+"/b";
}
}
}

AjaxHandler.ashx 文件代码(ashx扩展名属于自定义的,在新建时选择添加新项中的一般处理程序):
代码如下:

%@ WebHandler Language="C#" Class="AjaxHandler" %
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class AjaxHandler: IHttpHandler
{
public void ProcessRequest(System.Web.HttpContext context)
{
string str = context.Request["customerInfo"].ToString();
string msg = "服务器获得你的消息,时间:" + DateTime.Now.ToShortTimeString() + "br你的消息为:" + str + "br你的地址:" + context.Request.UserHostAddress;
context.Response.Write(msg);
context.Response.End();
}

public bool IsReusable
{
get
{
return true;
}
}
}

4、ASP.NET AJAX Control Toolkit 扩展控件的应用
Ajax扩展控件在VS2800中就有,但需要安装一下。具体安装方法见相关文章(我的博客中就有)。下面介绍其中两个最让人心动的控件:AutoCompleteExtender控件(文本框自动下拉列表查找控件)和CalendarExtender控件(选择日期控件)

AutoCompleteExtender控件的使用:
   使用AutoCompleteExtender控件为了实现自动完成功能及动态绑定数据,例如谷歌或百度搜索栏自动查找列表效果。在后台绑定数据库中相应的数据,如输入拼音或输简称后即可自动查找全称,鼠标点选实现快速录入。
使用步骤如下:
  第一步:在input.aspx窗体中添加一个TextBox控件,取名txtdep,添加扩展程序并选取AutoCompleteExtender控件。
  拖进设计界面后代码如下所示:
代码如下:

asp:TextBox ID="txtdep" runat="server" /asp:TextBox
cc1:AutoCompleteExtender ID="txtdep_AutoCompleteExtender" runat="server" EnableCaching="true" DelimiterCharacters="" Enabled="True" ServicePath=" " TargetControlID="txtdep" /cc1:AutoCompleteExtender
  
第二步:在Web.config文件中appSettings节添加数据库连接字符串,为连接数据库做准备:
代码如下:

appSettings
 add key="ConnString" value="server=(local);uid=sa;pwd=;persist security info=False;initial catalog= demo;Max Pool Size=1000"/
/appSettings

其中,server为SQL服务器名称,案例为本地,uid、pwd为SQL Server用户名和密码,initial catalog为要连接的数据库,,请根据实际情况填写。
  第三步:建立Web服务(WebService)。要使用AutoCompleteExtender,我们要通过Web服务传递数据。在解决方案资源管理器单击项目-〉添加新项-〉Web服务。这里使用了默认的名称WebService.asmx。
 WebService.asmx的代码修改如下:
代码如下:

using System.Collections;
using System.Web;
using System.Web.Services;
using System.Collections.Generic;
using System.Web.Services.Protocols;
using System.Data;
using System.Data.SqlClient;
using AjaxControlToolkit;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
//若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
[System.Web.Script.Services.ScriptService]//
必需,告诉.net runtime该WebService被允许从客户端调用
public class WebService : System.Web.Services.WebService
 {
    public WebService () {     }
     //构建Web服务的函数
  [WebMethod]
    public string[] getdepalist(string prefixText,int count)
{
//连接数据库
        string sqlstr = System.Configuration.ConfigurationSettings.AppSettings["ConnString"];
        SqlConnection sqlcon=new SqlConnection(sqlstr);
//从数据库中的表里用select语句返回查找结果
        string mysql = "select Area_Full from ST_Area where Area_Full like" + "'" + prefixText + "%' or Area_Spell like" + "'" + prefixText + "%'" ;
//使用SqlDataAdapter对控件进行数据的填充
        SqlDataAdapter da= new SqlDataAdapter(mysql, sqlcon);
        DataSet ds=new DataSet();
        if (count == 0)
        { count = 10;}
        da.Fill(ds, "Depa_Full");
//List是一个集合,根据特殊条件找到我们所需要的值
        Liststring items = new Liststring(count);
        for (int i = 1; i = ds.Tables["Depa_Full"].Rows.Count; i++)
        {
            items.Add(ds.Tables["Depa_Full"].Rows[i - 1][0].ToString().Trim());                  
        }
        return items.ToArray();
}
}

 第四步:设置AutoCompleteExtender控件,具体设置代码如下:
代码如下:

ajaxToolkit:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server"
        TargetControlID="TextBox1"
        ServicePath="WebService.asmx"
        ServiceMethod="getdepalist "
MinimumPrefixLength="0"
/ajaxToolkit:AutoCompleteExtender

  其中,ServicePath是指Web服务的文件名。ServiceMethod是指调用Web服务的函数名。MinimumPrefixLength是指输入多少个字符后开始列出输入提示列表。

CalendarExtender控件使用:
CalendarExtender控件的使用非常简单:
  在Web窗体中添加ScriptManager控件,添加textbox,取名txtreptime,点击“添加扩展程序”,在弹出的“扩展程序向导”对话框中选择CalendarExtender控件,即可。Web窗体源页面相应代码为:
代码如下:

divasp:ScriptManager ID="ScriptManager1" runat="server"
EnableScriptGlobalization="true"
/asp:ScriptManager/div
asp:TextBox ID="txtreptime" runat="server"/asp:TextBox
                cc1:CalendarExtender ID="txtreptime_CalendarExtender" runat="server"                     Enabled="True"
 Format="yyyy-MM-dd"
 TargetControlID="txtreptime" /cc1:CalendarExtender

其中,EnableScriptGlobalization="true"自加,使控件显示中文;Format="yyyy-MM-dd"自加,控制时间的格式。

以上是对两个扩展控件的案例的介绍,希望大家举一反三,更好的在实践中应用!

在应用中可能出现的问题:如ASP.NET验证控件在自定义控件使用中,出现错误,不能使用验证控件。为了避免错误,完全可以采取Javastript脚本来验证(即RegExp对象,使用正则表达式)。

AJAX个人学习笔记到此,基本上算是结束了,有很多本人认为不算重要的地方,没有囊括其中,有兴趣的朋友可以查阅相关资料和书籍。毕竟这只是一份学习笔记,侧重点是突出重要知识点。
介绍Ajax Control Toolkit 34个服务器端控件 主要属性及应用 可以查看下一篇文章。

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/webkaifa/)
展开更多 50%)
分享

猜你喜欢

揭开AJAX神秘的面纱(AJAX个人学习笔记)

Web开发
揭开AJAX神秘的面纱(AJAX个人学习笔记)

一个简单例子教你揭开AJAX神秘面纱

Web开发
一个简单例子教你揭开AJAX神秘面纱

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

Ajax核心概念的神秘面纱(1)

Web开发
Ajax核心概念的神秘面纱(1)

Ajax核心概念的神秘面纱(6)

Web开发
Ajax核心概念的神秘面纱(6)

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

Ajax核心概念的神秘面纱(4)

Web开发
Ajax核心概念的神秘面纱(4)

Ajax核心概念的神秘面纱(2)

Web开发
Ajax核心概念的神秘面纱(2)

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

ajax 调用后台方法大家可以讨论下

ajax 调用后台方法大家可以讨论下

SQLServer 2008 新增T-SQL 简写语法

SQLServer 2008 新增T-SQL 简写语法
下拉加载更多内容 ↓