Presentation is loading. Please wait.

Presentation is loading. Please wait.

AJAX技术入门.

Similar presentations


Presentation on theme: "AJAX技术入门."— Presentation transcript:

1 AJAX技术入门

2 提纲 走进AJAX AJAX的思维方式 AJAX的技术核心 AJAX应用实例 AJAX的优缺点 AJAX开发工具

3 走进AJAX A J X synchronous avaScript nd ML Jesse James Garrett
2005年的2月 《Ajax: A New Approach to Web Applications XML》 A J X synchronous avaScript nd ML

4 走进AJAX 老技术,新思想 (1)使用XHTML和CSS的基于标准的表示技术 (2)使用DOM进行动态显示和交互
(3)使用XML和XSLT进行数据交换和处理 (4)使用XMLHttpRequest进行异步数据检索 (5)使用Javascript将以上技术融合在一起 老技术,新思想

5 走进AJAX

6 走进AJAX GOOGLE

7 走进AJAX GOOGLE

8 走进AJAX Microsoft Yahoo! Amazone Baidu 163 Sina Sohu 。。。。。。

9 走进AJAX (1)改善表单验证方式,不再需要打开新页面,也不再需要将整个页面数据提交
(2)不需刷新页面就可改变页面内容,减少用户等待时间 。 (3)按需获取数据,每次只从服务器端获取需要的数据 。 (4)读取外部数据,进行数据处理整合 。 (5)异步与服务器进行交互,在交互过程中用户无需等待,仍可继续操作

10 提纲: 走进AJAX AJAX的思维方式 AJAX的技术核心 AJAX应用实例 AJAX的优缺点 AJAX开发工具

11 AJAX思维方式: 我们就通过用户名校验这个简单的例子来看看传统Web应用和AJAX应用开发思维的不同之处。
这个最简单的例子需求如下:用户在页面的文本框中输入想注册的用户名,然后点击校验按钮,如果输入的用户名为“wangxingkui”,则提示用户名已经存在,请重新输入,否则提示用户名尚未存在,可以使用此用户名进行注册。

12 AJAX思维方式: 问题分析: 对于校验用户名的需求,我们需要一个html页面和一个servlet程序。Html页面中包含文本框和提交按钮,他们位于一个form表单中,这个表单将请求提交给servlet程序,servlet程序判断当前的用户名是否是“wangxingkui”,并给出相应的提示,同时servlet中还生成一个链接,用于返回html页面。

13 AJAX思维方式:

14 AJAX思维方式: 从这个例子我们可以看到,传统Web开发思维模式的一个特点是通过form表单提交请求信息,然后转向一个新的页面处理请求,并显示服务器端返回的信息。 你可以尝试运行一下这些代码,你会发现作为用户的你经历了:在浏览器中输入用户名->点击按钮提交用户名给Servlet->浏览器转向Servlet的页面->等待Servlet处理->Servlet返回响应信息->浏览器中看到Servlet页面的响应信息,当然这其中有几个过程可能时间短暂到你没有注意,但这些过程是确实存在。

15 AJAX思维方式:

16 AJAX思维方式: 问题分析: 对于校验用户名的需求,我们需要一个html页面和一个servlet程序。
Html页面中包含文本框和校验按钮,点击提交按钮以后,我需要通过javascript获取文本框中的数据,然后通过XMLHttprequest发送数据给servlet,此外还需要准备用于接收响应的javascript函数,接收到servlet的提示信息后,我需要将这些信息动态的写在页面上。servlet程序判断当前的用户名是否是“wangxingkui”,并给出相应的提示。

17 AJAX思维方式: 注意,AJAX模式下问题分析的方式已经发生了变化:
servlet不需要返回html页面的链接了,因为我们不需要跳转到servlet表示的页面中,我们只需要获得servlet页面产生的结果 html页面中我不用表单提交数据了,我的数据通过javascript来获取,然后通过一个叫做XMLHttprequest的对象发送个servlet。而且我没有做页面跳转 我需要一个接收servlet响应信息的javascript函数,我没有进入servelt代表的页面查看响应信息,而是把servlet的响应信息接收回来,再显示在我当前的页面上。

18 AJAX思维方式: 当你运行上面的程序,你会发现从用户的角度来看,与传统Web应用模式的流程相比,AJAX应用模式的流程是不同的。
AJAX应用的流程是:在浏览器中输入数据->点击按钮提交请求->用户可以继续做其他事情;Servlet在处理数据,并发回数据->浏览器收到响应->浏览器中的当前页面显示响应结果,这其中仍然有些过程由于时间短暂使你忽略了它的错在,但实际上这些过程都是存在的。 两个流程的对比让我们看到的显而易见的差别就是AJAX应用中没有向新页面跳转,用户不需要处于无事可做的等待中。

19 AJAX思维方式:

20 AJAX思维方式:

21 AJAX思维方式:

22 AJAX参考书籍 JavaScript Professional Projects DHTML手册.chm

23 AJAX参考书籍 DOM文档对象中文手册.chm

24 AJAX参考书籍 CSS中文手册.chm

25 AJAX参考书籍 CSS中文手册.chm

26 AJAX参考书籍 Professional Ajax(AJAX高级程序设计):
本书目前已有翻译版在国内销售。本书除了介绍AJAX的基本知识以外,在跨浏览器实现XML处理和Webservice处理上做了详细介绍,也有一个如何建立自己的Gmail的示例,另外还介绍了三个分别为PHP,JAVA和.NET平台服务的AJAX服务器端框架。

27 AJAX参考书籍 Foundations Of AJAX(AJAX基础教程):
号称国内第一本AJAX的图书,在国外也很受欢迎的一本书。个人认为书中比较有用的是介绍了很多AJAX开发的辅助工具,同时有过个实用的AJAX示例。

28 AJAX参考书籍 Pragmatic AJAX(AJAX修炼之道-Web2.0入门):
国内已有此书的翻译版。本书比较短小精悍,其中比较特色的是介绍了如何建立一个自己的Google Maps,并在AJAX UI方面做了较多描述,另外简要介绍了一些浏览器端AJAX框架,以及AJAX和PHP联合开发的问题。

29 AJAX参考书籍 AJAX For DUMMIES(AJAX傻瓜教程):
本书编排和版面设计上比较有特色。内容上即介绍了AJAX的基本知识,也介绍了AJAX的一些框架。比较有特色的部分是给出了AJAX开发的十个需要了解的问题以及一些有用的AJAX资源。

30 AJAX参考书籍 AJAX In Action(AJAX实战):
国内已有此书的翻译版本。一本将近700页的AJAX图书,和其他AJAX图书相比分量很重,介绍内容非常广泛。可以作为一本AJAX的参考书。书中最后介绍了目前几乎所有的AJAX浏览器及服务器端框架,对于大家选择AJAX框架有一定的帮助。

31 AJAX参考书籍 AJAX Hacks: 国外著名IT出版社O'Reilly的AJAX图书,国内有影印版。该书以一个个Hack条目来介绍AJAX,其中有一半的篇幅介绍了我们前面提到的几个流行的AJAX框架:DWR,Ruby On Rails,Rico,script.aculo.us。同时还有一些实用的示例供大家参考。

32 AJAX参考书籍 另外有两个国内高手写的AJAX入门电子书可供参考: 《AJAX开发简略》 《AJAX——新手快车道》。
《AJAX——新手快车道》的作者文笔风格比较有趣,根据他blog上所说也会出一本AJAX方面的书,但目前还没有看到。

33 AJAX参考书籍 《AJAX开发简略》的作者柯自聪今年出版了一本AJAX方面的书籍《AJAX开发精要-概念、案例与框架》,可以在书店买到。

34 AJAX参考书籍 这两本书也是国外的作品。 《AJAX Design Patterns》这本书网上评价也很好,属于中高级的AJAX书籍。
《Head Rush AJAX》属于Head Rush系列书中的一套,根据以前看过的《Head Rush Java》来看,Head Rush系列书编排非常有特色,里面有大量的插图和手写文字,内容上比较浅显易懂,作为趣味入门书是个不错的选择。

35 提纲: 走进AJAX AJAX的思维方式 AJAX的技术核心 AJAX应用实例 AJAX的优缺点 AJAX开发工具

36 AJAX技术核心 XMLHttpRequest对象 DOM与HTML DOM与XML 面向对象的Javascript

37 AJAX技术核心 Asynchronous XMLHttpRequest 最早是在IE5.0中以ActiveX组件的形式出现的
后来Mozilla,Safari,Opera等浏览器厂商都支持了XMLHttpRequest 由于XMLHttpRequest并不是W3C的标准,因此在各个浏览器的实现上也有所不同。 IE“独树一帜”,仍然是以ActiveX组件的方式来创建XMLHttpRequest对象 其他浏览器则可以直接创建javascript的XMLHttpRequest对象。

38 AJAX技术核心 <input type="button" value="检验" onclick="submit()"/>
首先我们发现和传统Web开发模式不同,页面中没有form,submit换成了一个button,在button的定义中,我们使用了一个onclick属性。 onclick属性的作用是在点击按钮时,调用该属性所指定的javascript函数。我们可以在onclick属性指定的javascript函数中使用XMLHttpReuqest对象来与服务器端程序(例如一个Servlet)进行数据传输。

39 AJAX技术核心 用户名:<input type="text" id="name"/>
这是因为在AJAX模式中,我们通常在javascript代码中通过DOM获得html页面中某个节点的值,因此我们一般都定义id属性,这部分的详细内容会在后面介绍。

40 AJAX技术核心 <div id="result"></div>
另外我们建立了一个div标签,div标签应该说是AJAX模式下很重要的一个html标签。 前面我们提到过的基于标准的表示技术,比较常用的一种方式就是用DIV+CSS替代talbe的方式来划分网页结构,div中放内容,css控制这些内容的展现形式。 除此之外,div的另一个常用之处就是用于放置动态加入网页中的内容,先建立一个没有内容那个div,再在Javascript代码中通过DOM动态的向其中添加内容,以保证在页面不刷新的情况下动态修改页面内容。这部分的详细内容也会在后面介绍。

41 AJAX技术核心 document.getElementById("result") document.getElementById("name").value document.getElementById的作用是根据id名获得对应的节点(某一个html标签的内容),我们这里分别用这个语句来获得div和文本框的节点;.value的作用是获得文本框的value属性值,也就是文本框中的内容。

42 AJAX技术核心 resultNode.innerHTML = "不能建立XMLHttpRequest对象"; resultNode.innerHTML这样的用法是为了设置某个节点中的html的内容,这里resultNode代表的是div那个节点,这句话的效果是使div的内容变成了<div id="result">不能建立XMLHttpRequest对象</div>,这样我们就会在页面中看到这行提示信息。

43 AJAX技术核心 if(window.XMLHttpRequest){ xmlhttp = new XMLHttpRequest();
if(xmlhttp.overrideMimetype){ xmlHttp.overrideMimeType("text/xml"); } } else if (window.ActiveXObject) { var MSXML = ['MSXML2.XMLHTTP.6.0','MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0','MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP','Microsoft.XMLHTTP']; for(var n = 0; n < MSXML.length; n ++){ try{ xmlhttp = new ActiveXObject(MSXML[n]); break; }catch(e){} If(xmlhttp == null){ resultNode.innerHTML = "不能建立XMLHttpRequest对象"; return false;

44 AJAX技术核心 “window.XMLHttpRequest”为true时表示当前浏览器是IE7或其他浏览器,我们就可以使用new XMLHttpRequest()的方式来创建一个XMLHttpRequest对象 if(xmlhttp.overrideMimetype)这个逻辑的作用是解决部分版本的Mozilla在服务器响应头信息没有XML时不能正常工作的问题。

45 AJAX技术核心 “window.ActiveXObject”为true时表示当前的浏览器为IE6.0及以下的版本,要使用new ActiveXObject(控件名)的方式来创建一个XMLHttpRequest对象 这里需要注意的是不同版本IE中用于建立XMLHttpRequest对象的控件版本很多 如果使用MSXML数组中的某一个控件名称成功建立了XMLHttpRequest对象,则跳出循环,如果建立失败会有异常抛出,被catch以后继续进行循环,尝试下一个控件名称 这里的控件名称是按照从新到老的顺序排列的,这样可以保证使用较新版本IE的用户可以较早成功建立XMLHttpRequest对象。 如果没有建立成功XMLHttpRequest对象,则不能继续后面与服务器端交互的工作,函数只能返回。

46 AJAX技术核心 xmlhttp.onreadystatechange=callback; 然后我们做的工作是设置一个回调函数
回想前面我们说过的AJAX的模式的特点,由于我们采用异步交互的模型,不像同步模式一样可以直接接收响应内容,因此我们需要告诉AJAX引擎当响应数据回来时我要做一些工作,这些工作就是回调函数中的内容。 这里需要注意的是设置回调函数时应该只给出回调函数的名称,后面不要带括号,因为带上括号就变成让XMLHttpRequest对象的onreadystatechange属性值等于回调函数的返回值了。

47 AJAX技术核心 xmlhttp.open("GET","AJAXServer?name=" + encodeURI(encodeURI(name)),true); 接下来要做的工作是建立对服务器的调用。这里第一个参数表示http连接的方法, 一般我们使用“GET”或“POST”方式,两种方式的区别会在后面阐述。 第二个参数是服务器端地址,由于使用GET方式,因此要传送给服务器端的数据也在URL中,这里我们使用了两个encodeURI,目的是为了解决URL中的中文信息在服务器端解码的问题,配合服务器端的URLDecoder.decode(old,“UTF-8”)语句可以保证中文信息在服务器端也可以正常被解出。 第三个参数表示是否采用异步方式进行传输,其中true表示采用异步方式,我们在AJAX中看重的就是异步方式,因此这个参数我们通常使用true。

48 AJAX技术核心 xmlhttp.send(null); 再接着就是向服务器端发送数据,这里由于已经在URL中包含了发送给服务器的数据,因此在send时就不需要参数了,后面会讲到对于POST模式,这里的使用方式会有不同。

49 AJAX技术核心 function callback(){ if(xmlhttp.readyState == 4){
resultNode.innerHTML = xmlhttp.responseText; } else{ resultNode.innerHTML = "服务器故障"; }

50 AJAX技术核心 这里readyState=4时表示服务器端的响应数据已经被全部接收,readyState还有其他状态,后面会进行详细介绍。
Status=200表示http连接状态正常,如果不是200,则表示http连接有误,此时回来的数据也不是我们需要的。 当响应数据全部接收并且http连接状态正确时,我们就可以接收响应的数据了,这里使用了xmlhttp.responseText用于以文本形式接收响应的数据,当然也可以用XML方式接收,后面会做详细介绍。

51 AJAX技术核心 abort() 停止当前请求 getAllResponseHeaders()
方法 描述 abort() 停止当前请求 getAllResponseHeaders() 返回包含HTTP请求的所有响应头信息,其中响应头包括Content-Length,Date,URI等内容。 返回值是一个字符串,包含所有头信息,其中每一个键名和键值用冒号分开,每一组键之间用CR和LF(回车加换行符)来分隔 getResponseHeader(String header) 返回HTTP请求的响应头中指定的键名header对应的值

52 AJAX技术核心 方法 描述 open (String method,String url,boolean asynch,String username,String password) 建立对服务器的调用。 其中method表示HTTP调用方法。一般使用“GET”,“POST” url表示调用的服务器的地址 asynch表示是否采用异步方式,true表示异步 后两个参数可以不指定,username和password分别表示用户名和密码,提供http认证机制需要的用户名和密码 send(content) 向服务器发出请求,如果采用异步方式,该方法会立即返回。 Content可以不指定,其内容可以是DOM对象,输入流或是字符串。 setRequestHeader(String header,String value) 设置HTTP请求中的指定首部header的值为value。 此方法需在open方法以后调用。

53 AJAX技术核心 属性 描述 onreadystatechange
请求状态改变的事件触发器(readyState变化时会调用此方法)。通常是一个javascript函数 readyState 请求状态 0=未初始化。 1=open方法成功调用以后。 2=服务器已经应答客户端的请求。 3=交互中。Http头信息已经接收,响应数据尚未接收。 4=完成。数据接收完成。

54 AJAX技术核心 responseText 服务器返回的文本内容 responseXML 服务器返回的兼容DOM的XML内容 status
属性 描述 responseText 服务器返回的文本内容 responseXML 服务器返回的兼容DOM的XML内容 status 服务器返回状态码。200表示“成功”,404表示“未找到” statusText 服务器返回状态码的文本信息。

55 AJAX技术核心 GET和POST的区别:
“GET”和“POST”的一个重要区别在于,“GET”方式传递给服务器的信息一般以后缀参数方式存在于URL地址中,而URL的长度通常都有限制,这也就限制了“GET”方式传递给服务器的内容大小 而“POST”方式传递给服务器的信息并不位于URL地址中,所以没有大小限制。 通常我们在服务器端的Servlet中,doGet和doPost做的是一样的工作,因此由于POST传递信息没有大小限制,我们实际应用中比较多的会使用POST。

56 AJAX技术核心 xmlhttp.open("GET","AJAXServer?name=" + encodeURI(encodeURI(name)),true); xmlhttp.send(null); xmlhttp.open("POST","AJAXServer",true); xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xmlhttp.send("name=" + encodeURI(encodeURI(name)));

57 AJAX技术核心 (源码网整理,www.codepub.com)
每次readyState变化时onreadystatechange属性对应的函数都会被调用。 之前我们曾经说过onreadystatechange属性设置回调函数是为了在接收到响应数据后对响应数据进行处理,之所以这样说是因为我们通常只关心收到响应数据以后时的工作,也就是readyState=4时的状态,因此我们的回调函数中也用readyState==4来做判断。 (源码网整理,

58 AJAX技术核心 status和statusText属性:
它的值是http的状态码,我们通常只在status=200时才进行响应数据处理,但也可根据具体情况在status为其他值时做一些处理。 statusText属性一般用于status不为200时显示详细的http错误状态信息

59 AJAX技术核心 responseText与responseXML属性:
无论服务器端返回的是XML还是普通的文本内容,html内容,都可以使用responseText属性来获得服务器端的返回值。 当服务器端返回的不是XML内容是,不同的浏览器在获取responseXML属性值时略有不同,IE仍然会获取到一个DOM对象,只不过内容是空的,而FireFox获取到的则是一个null

60 AJAX技术核心 如果服务器端要返回普通文本内容,html内容,一般在服务器端会设置响应头信息中的"Content-Type"为text/html,同时为了保证中文信息不会出现乱码,还会根据需要设置"Content-Type"中charset。 如果服务器端要返回xml,首先返回的数据一定要是一个DOM兼容的xml字串,其次需要在服务器端设置响应头信息中的“Content-Type”为text/xml。这样在浏览器端的Javascript代码中我们可以通过responseXML属性获得一个DOM兼容的XML对象,通过DOM的方式操作XML,这部分内容会在后面介绍。

61 AJAX技术核心 还有一点需要说明的是虽然AJAX倡导使用传输XML数据,但是正如Jesse James Garrett老兄在他提出AJAX概念的那篇文章中的FAQ部分说的一样并不是AJAX模式的程序一定要用XML作为传输数据 XML数据的优势是不同系统之间可以交互一种统一结构的数据,这样你的服务器端程序即可以和AJAX的客户端交互,也可以方便的和其他类型客户端交互。 很多时候,在AJAX模式的程序中使用纯文本内容或是自定义的数据结构进行数据传输会更方便,实际上Google几个有名的AJAX模式产品使用的都不是XML的数据。

62 AJAX技术核心 总结——AJAX应用的五个步骤: 1.建立XMLHttpRequest对象 2.设置回调函数
3.使用open方法与服务器建立链接 4.向服务器端发送数据 5.在回调函数针对不同响应状态进行处理

63 AJAX技术核心 需要注意的内容: 1.不同浏览器下XMLHttpRequest对象的不同的建立方式 2.设置回调函数时不要加括号
3. open方法三个参数含义,此外还需要注意GET方式和POST方式服务器端地址的不同写法 4. GET方式和POST方式send的参数的不同之处,以及POST方式下send之前需要设置请求头信息的工作 5.如何判断正确的响应数据已经返回,此外还要注意如何获取响应数据内容。

64 AJAX技术核心 XMLHttpRequest的一个特殊安全问题: IE:访问跨域页面时会给出提示,用户确认后会访问
Mozilla FireFox及其他:不允许访问跨域页面

65 AJAX技术核心

66 AJAX技术核心 如何解决跨域问题?

67 AJAX技术核心 在浏览器端的代码中,我们需要在调用open方法之前判断一下要连接的地址是不是以http开头的,如果是则认为要访问的是跨域的资源,首先将当前url中的”?”变成”&”,这是因为将要连接的地址改为”Proxy?url=” + url以后,如果原来url地址中有参数的话,新的url地址中就会有两个“?”这会导致服务器端解析参数错误,”url=”之后的内容表示本来要访问的跨域资源的地址。 function convertURL(url){ if(url.substring(0,7) == " url = url.replace("?","&"); url = "Proxy?url=" + url; } return url;

68 AJAX技术核心 注意Proxy中针对GET方式和POST方式进行了分别的处理,其中GET方式仍然将参数信息拼到URL中,而POST方式则向HttpURLConnection的数据流中添加参数信息。 由于对本来请求的地址和其包含的参数进行了转换,导致url参数中只包含原来请求的地址信息,而原来请求的参数信息则需要我们解析出来和地址信息一起重新组成本来的请求URL,因此方法开头的一段while就做了这个工作。

69 AJAX技术核心 注意由于进入servelt之前参数信息已经被做过一次URLDecoder,因此这个时候参数信息中的中文信息传到真正要访问的servlet时解码会出现乱码,因此我们再拼接参数信息之前又再一次通过URLEncoder.encode方法对所有参数信息进行了一次编码,这样就解决了中文的乱码问题。 在从远端服务器读取数据时,要显示的指定输入流的编码格式,这样才可以保证通过BufferReader读到的内容不会有乱码信息。

70 AJAX技术核心 xmlhttp.setRequestHeader("Cache-Control","no-cache");
<meta http-equiv=Expires content=0> <meta http-equiv=Pragma content=no-cache> <meta http-equiv=Cache-Control content=no-cache> xmlhttp.setRequestHeader("Cache-Control","no-cache");

71 AJAX技术核心 if(url.indexOf("?") >= 0){
url = url + "&t=" + (new Date()).valueOf(); } else{ url = url + "?t=" + (new Date()).valueOf(); } 一个比较好的方法是给url地址最后加上时间戳,这样在浏览器看来每次请求的url地址都不一样,因此就不会出现缓存问题,我们一般采用如下方式。其中url是原始请求地址,代码中根据原url中是否已有参数信息来进行时间戳参数的增加。

72 AJAX技术核心 DOM(Document Object Model)被称作文档对象模型,它是语言和平台中立的接口,允许程序和脚本动态访问和更新文档的内容,结构和风格。 在AJAX中,DOM对于我们来说是HTML 和 XML 文档的一个应用程序接口,它可以把HTML,XML与AJAX中的开发语言Javascript连接起来。 Javascript中的DOM实现可以使得我们在AJAX中通过Javascript代码对HTML和XML数据进行DOM方式的操作,从而做到页面的动态修改更新和数据的提取处理。

73 AJAX技术核心 HTML的DOM和XML的DOM在API接口上基本一致,使用差别不大,但本质上有区别。
HTML的DOM是一个内存对象树,在浏览器中只保存一份,HTML的DOM修改HTML的内容会直接反应到浏览器中;而XML的DOM则可以创建多个,每个可以对应一个XML文本。

74 AJAX技术核心 DOM与HTML

75 AJAX技术核心 在DOM眼中,HTML是由很多不同类型的节点组成的,这些节点都属于NODE对象。
NODE对象有一个nodeType的属性可用于判断节点类型 接口 nodeType常量 nodeType值 备注 Element Node.ELEMENT_NODE 1 元素节点 Attr Node.ATTRIBUTE_NODE 2 节点属性 Text Node.TEXT_NODE 3 文本节点 Comment Node.COMMENT_NODE 8 注释的文本 Document Node.DOCUMENT_NODE 9 Document根节点

76 AJAX技术核心 元素节点是HTML中最常见的节点,页面中的<body>,<input>,<div>都是元素节点。 属性节点表示的是一个元素节点的某个属性,例如<input>中的value属性就可以被看作一个属性节点。 文本节点表示HTML页面中的一段文字信息,例如<div>Hello World</div>,其中的”Hello World”就是一个文本节点。

77 AJAX技术核心 注释文本节点也比较好理解,HTML的注释信息,<!—Comment Message-->比如这样一段内容就是一个注释文本节点。 根节点顾名思义,表示的是HTML的根,在Javascript中有一个特殊的对象document,它可以表示HTML的根节点,后面我们会介绍这个特殊对象有很多在AJAX中非常常用的方法。

78 AJAX技术核心 根节点的属性和方法 documentElement 表示文档的根元素节点
描述 documentElement 表示文档的根元素节点 在HTML文档中,它表示<html>这个标签代表的元素节点 方法 createAttribute() 用指定名字创建新的Attr节点对象。 方法参数为属性的名字 createComment() 用指定的字符串创建新的Comment节点对象。 方法参数为注释信息 createElement() 用指定的标记名创建新的Element节点对象。 方法参数为节点标签的名字

79 AJAX技术核心 根节点的属性和方法 createTextNode() 用指定的文本创建新的文本节点对象。 方法参数为文本信息
描述 createTextNode() 用指定的文本创建新的文本节点对象。 方法参数为文本信息 getElementById() 返回文档中具有指定id属性的Element节点。 方法参数为节点的id属性值 getElementsByTagName() 以数组方式返回文档中具有指定标记名的所有Element节点,其顺序为在文档中出现的顺序。标记名指的是像body,table这样的HTML标记名称。 方法参数为标记名称

80 AJAX技术核心 Element节点对象的常用方法都是对节点属性的操作。 属性 描述 tagName
元素的标记名字,例如<table>元素的标记名字为table。 HTML文档返回的标记名字均为大写。 方法 getAttribute() 以字符串形式返回指定属性的值 方法参数为属性名称 getAttributeNode() 以Attr节点对象的形式返回指定属性的值 getElementsByTabName() 以数组方式返回当前元素节点的子孙节点中中具有指定标记名的所有Element节点,其顺序为在文档中出现的顺序。 方法参数为节点的标记名

81 AJAX技术核心 Element节点对象的常用方法都是对节点属性的操作。 方法 描述 hasAttribute()
如果该元素具有指定名字的属性,则返回true removeAttribute() 从Element节点中删除指定的属性 方法参数为属性的名称 removeAttributeNode() 从Element节点的属性列表中删除指定的Attr节点 setAttribute() 把指定的属性设置为指定的字符串值,如果该属性不存在则添加一个新属性 方法的第一个参数为属性的名称 方法的第二个参数为属性的值 setAttributeNode() 把指定的Attr节点添加到该元素的属性列表中 方法的参数为Attr节点对象

82 AJAX技术核心 属性节点的属性 属性 描述 name 属性名 value 属性值

83 AJAX技术核心 Node对象的属性和方法如下所示 : 属性 描述 attributes 表示该节点的所有属性节点对象的数组
childNodes 表示当前节点的子节点的数组。如果没有子节点,则返回空数组 firstChild 返回当前节点的第一个子节点。如果没有子节点,则返回null lastChild 返回当前节点的最后一个子节点。如果没有子节点,则返回null nextSibling 返回当前节点的下一个兄弟节点。如果没有这样的节点,则返回null

84 AJAX技术核心 Node对象的属性和方法如下所示 : previousSibling
描述 previousSibling 返回当前节点的上一个兄弟节点。如果没有这样的节点则返回null nodeName 返回节点的名字,对于Element节点表示Element的标记名称 nodeType 代表节点的类型 nodeValue 代表节点的内容。对于Text节点,nodeValue的值是文本内容。对于注释节点,nodeValue的值是注释内容。对于属性节点,nodeValue的值是属性值。对于其他节点,nodeValue的值可能为null。 parentNode 返回当前节点的父节点。如果没有父节点,则返回null

85 AJAX技术核心 Node对象的属性和方法如下所示 : 方法 描述 appendChild()
给当前节点增加一个子节点。增加的子节点位于当前节点的所有子节点的末尾。 方法参数为Node对象。 cloneNode() 复制当前节点,或者复制当前节点以及它的所有子孙节点。 方法参数为true或false。True表示递归的复制所有子孙节点,false表示只复制当前节点。 hasChildNodes() 如果当前节点拥有子节点,则返回true

86 AJAX技术核心 Node对象的属性和方法如下所示 : 方法 描述 insertBefore()
插入一个节点,位置在当前节点的指定子节点之前。如果该节点已经存在,则删除原节点后再插入新的节点。如果指定子节点不存在,则执行效果和appendChild方法相同。 方法第一个参数是要插入的节点。 方法第二个参数是当前节点的指定子节点,新插入的节点位于这个节点之前。 removeChild() 从文档树中删除并返回指定的子节点。 方法的参数是要删除的子节点 replaceChild() 从文档树中删除并返回指定的子节点,用另一个节点替换它。 方法第一个参数是新的子节点。 方法第二个参数是被替换的子节点。

87 AJAX技术核心 <books> <book> <author>Peter</author>
<name>Hello AJAX</name> </book> <author>Jack</author> <name>AJAX Puzzle</name> </books>

88 AJAX技术核心 HTML的DOM中我们提到并大量使用了document这个Javascirpt的内置对象,请注意这个对象仅仅可以表示HTML的根节点。 而对于XML的DOM来说,每一个XML都一个根节点。 如果我们想建立一个节点的时候,也要使用XML的根节点来创建,这样才能保证新建的节点可以被添加到XML中,从而改变XML的内容。

89 AJAX技术核心 由于xml变量是根元素节点,因此我们用“xml.parentNode”就可以获得这个XML的根节点
function test(){ var xml = loadXML(false,"<books><book>123</book></books>"); var root = xml.parentNode; var node = root.createElement("book"); var text = root.createTextNode("abc"); node.appendChild(text); xml.appendChild(node); alert(xml.lastChild.childNodes[0].nodeValue); } 由于xml变量是根元素节点,因此我们用“xml.parentNode”就可以获得这个XML的根节点 然后我们用根节点新建元素和文本节点,并把他们加入到当前的XML中,最后通过alert语句来验证新的内容被加入到XML文档中。

90 AJAX技术核心 什么是空白信息呢? 对于HTML来说,body的子孙节点中(请注意,并不是HTML页面中的所有位置都有这个空白信息的概念),如果两个元素节点之间有空格,回车这样的不包含任何文字信息的内容,那这些信息就都是空白信息(注意如果一段文字信息之中包含空格,回车,制表符,则这些不算是空白信息) 对于XML来说根节点的子孙节点中,如果两个元素节点之间有空格,回车这样的不包含任何文字信息的内容,那这些信息就都是空白信息。

91 AJAX技术核心 在IE中,这些空白信息很没有地位
IE的DOM实现在解析HTML时,如果两个元素节点之间全是空白信息,则都会被过滤掉,如果两个元素节点之间既有空白信息又有文本信息,则文字信息之前的空白信息都会被过滤掉,文本信息之后的空白信息中空格制表符会被保留,换行符则被过滤 而IE的DOM实现在解析XML时,如果两个元素节点之间全是空白信息,则都会被过滤掉,如果两个元素节点之间既有空白信息又有文本信息,则空白信息都会被保留。

92 AJAX技术核心 在FireFox中,这些空白信息则基本被一视同仁
FireFox的DOM实现在解析HTML时,如果两个元素节点之间全是空白信息,则都会被保留,如果两个元素节点之间既有空白信息又有文本信息,则文字信息之前的空白信息都会被过保留,文本信息之后的空白信息则都被过滤 FireFox的DOM实现在解析XML时会把这些空白信息都保留。

93 AJAX技术核心 由于两个元素节点之间既有空白信息又有文本信息时我们无法确定其中的空白信息是否无用,因此我们只针对两个元素节点之前全部是空白信息的情况进行处理。 function removeBlank(xml) { if(xml.childNodes.length > 1){ for (var loopIndex = 0; loopIndex < xml.childNodes.length; loopIndex++) { var currentNode = xml.childNodes[loopIndex]; if (currentNode.nodeType == 1) { removeBlank(currentNode); } if (((/^\s+$/.test(currentNode.nodeValue))) &&(currentNode.nodeType == 3)) { xml.removeChild(xml.childNodes[loopIndex--]); }}}

94 AJAX技术核心 在Javascript中,一段正则表达式被放在两个”/”之间,通过/s$/.test(str)这样的语句就可以判断str中是否包含”s$”代表的正则表达式,如果包含则返回true。 /^\s+$/这个正则表达式的作用是判断字串的每一行中是否从开头到结尾包含一个或多个空格

95 AJAX技术核心 getElementById方法在解析XML的时候是否适合呢? 首先XML中每一个元素节点不一定有id属性
其次XML中的两个元素节点可能有相同的id属性,这样getElementById这个方法就不再能保证找到我们需要的唯一节点了 因此这种方式并不适合XML的解析。

96 AJAX技术核心 XPATH是什么?全称是XML Path Language(XML路径语言),适用于确定XML文档中某节点位置的语言。
我们可以把它当作类似于SQL一样的查询语言,通过给出XPTAH路径信息(就像SQL命令一样)就可以从XML中查找出符合条件的节点(就像从数据库中返回需要的数据一样)。

97 AJAX技术核心 在IE6.0及其以后版本中我们可以使用同样的方式来访问任意深度的XML数据,这给XML数据的解析操作带来了便利。
使用过DOM4j的人可能都知道可以利用其中的selectSingleNode和selectNodes 方法直接给出XPATH地址来获取任意深度的一个或多个节点。 在IE6.0及其以后版本中我们可以使用同样的方式来访问任意深度的XML数据,这给XML数据的解析操作带来了便利。 但是在FireFox等浏览器中,则是使用了w3c标准的XPATH处理方式,没有IE这么简单的方式。

98 AJAX技术核心 所有的author节点 获取所有isdn属性节点 获取所有name节点中的文本内容 有isdn属性的book节点
<books> <book isdn="0001"> <author>Wang</author> <name>AJAX Professional</name> <price>35</price> </book> <book isdn="0002"> <author>Lee</author> <name>AJAX In Action</name> <price>65</price> <book> <author>Zhu</author> <name>AJAX For Dummies</name> <price>40</price> </books> 所有的author节点 获取所有isdn属性节点 获取所有name节点中的文本内容 有isdn属性的book节点 获得子节点price值大于35且isdn等于0002的所有book节点 获得子节点price值大于35或isdn等于0002的所有book节点

99 AJAX技术核心 如果当前节点是根节点:“book/author”
不管当前节点是什么都可以用:”/books/book/author”或”//author”或”//book/author” XPATH的路径即可以是相对路径,也可以是绝对路径。 当以”/”开头,则表示绝对路径方式,从根节点开始查找 如果不以”/”开头,则表示相对路径,这个时候相对的是我们前面的封装函数中的第一个参数所表示的节点对象。注意,如果当前节点是某一个book节点,我们只能通过”author”找到这个book节点下的author节点。 如果以”//”开头,则直接找整个文档中符合条件的节点,不管这个节点在哪里,找到所有的author节点。

100 AJAX技术核心 获取属性节点和获取元素节点在路径表示上是一样的,即可以用相对路径,也可以用绝对路径,还可以用”//”查找任意满足的节点。
获取属性节点和获取元素节点在路径表示上是一样的,即可以用相对路径,也可以用绝对路径,还可以用”//”查找任意满足的节点。

101 AJAX技术核心 获取文本节点和前面两个在路径表示上也是一样的。 不同之处在于需要使用text()方法
如果当前节点是根节点:“book/name/text()” 不管当前节点是什么都可以用:”/books/book/name/text()”或”//name/text()”或”//book/ name/text()” 获取文本节点和前面两个在路径表示上也是一样的。 不同之处在于需要使用text()方法

102 AJAX技术核心 如果当前节点是根节点:“book[@isdn]”
在XPATH中可以在[]中指定条件,从而只获得满足某些条件的节点

103 AJAX技术核心 | book[price>35]” | | //book[price>35]” 和(5)的需求不同之处是我们需要的不是与关系,而是或关系,这个时候我们可以使用”|”表示或关系,”|”可以同时连接多个XPATH路径。 这里需要注意的是这样返回的节点数组是不会有重复信息的,例如我们这个例子中price>35的节点有两个,其中一个满足isdn=’0002’这个条件,最后的返回结果中只有两个节点,而不会有三个节点。

104 AJAX技术核心 DOM除了可以解析和修改XML以外,还可以从字符串或xml文件中加载XML,或者新建一个空的XML
XML的加载和上一节XPATH面临的问题一样,IE和FireFox中处理方式差异很大,因此为了使用方便,我们进行了封装。

105 AJAX技术核心 在IE的装载过程中,仍然使用了ActiveX对象来做工作
在IE中,新建了对象以后还需要设置使用同步方式装载文档,这和我们使用XMLHttpRequest的方式不同,当然如果你需要,也可以异步的装载文档,这个时候就需要像XMLHttpRequest对象一样设置onreadystatechange属性了。

106 AJAX技术核心 IE中装载XML的对象提供了两个方法分别用于装载XML文件和包含XML的字符串。最后我们返回的是XML文档的根元素节点。如果在实际应用中需要返回根节点,只要将return的内容从xmlDoc.documentElement变成xmlDoc就可以了。

107 AJAX技术核心 在FireFox的装载过程中,装载XML文件和装载XML字符串是不一样的。
如果需要装载XML文件,应该首先通过document.implementation.createDocument建立一个空文档,然后调用文档对象的load方法来装载。

108 AJAX技术核心 而如果要装载XML字符串,则是需要建立一个DOMParser的对象,然后通过parseFromString方法进行装载,返回文档对象。 需要注意的是在FireFox中,只有装载XML文件才会需要设置同步方式装载文档,如果需要像XMLHttpRequest一样异步处理,就需要设置onload属性,而且FireFox中处理装载完成的情况和IE也不一样,不是XMLHttpRequest的那种需要判断readyState的方式,而是直接会执行onload属性对应的方法中的内容。

109 AJAX技术核心 最后还有一点要说明的是,在IE和FireFox中装载XML文件时,会有和XMLHttpRequest对象一样的安全性限制,也就是不能访问跨域的XML数据。由于通常情况下不会装载跨域的XML数据,因此这个问题不是很麻烦,如果却是有需要装载跨域XML数据,那么可以考虑使用前面解决XMLHttpReuqest对象跨域问题的思路来解决这个问题。

110 AJAX技术核心 作为一个脚本语言,Javascript和我们目前常用的Java,C#,C++在使用上还是有一些差别的。

111 AJAX技术核心 Java,c#,c++这些面向对象语言都是强类型,而Javascript是一种无类型语言,在Java等语言中,我们的任何一个常量变量都是有类型信息的,可能是整数型,字符串形抑或是用户定义的类型 而在Javascript中,任何的变量我们都用var来标识,回想前面看到的代码,无论是数字,字符串,还是节点对象,都是一个var。

112 AJAX技术核心 Java,c#,c++这些面向对象语言很显著的一个特点就是有类这个概念的存在,而且有基于类的继承机制。
而在Javascript语言中则没有类这个概念,而且也没有基于类的继承机制。从以上两点来说,javascript不会是一个传统意义上的面向对象语言。

113 AJAX技术核心 我们经常见到的Javasript代码都是位于一个一个的function中,如果应用复杂一些,我们会看到一个function调用另一个或另几个function,这种方式不禁让我们想起了c语言中面向过程的开发方式。 在AJAX开发中,Javascript的代码数量会比原来我们做Web开发要多出很多,因为AJAX的主要工作代码都是需要使用Javascript来编写的,这个时候如果采用面向过程的方式从一个function调用另一个function,那么当代码数量越来越多时,管理将变得困难,代码出错的可能性将增多。因此,我们会期望可以在Javascript中使用面向对象的方式。

114 AJAX技术核心 虽然Javascript不是一门传统意义上的面向对象的语言,但是其中还是包含了一些类面向对象的特征,我们完全可以在Javascript中“模拟”面向对象的一些方式 接下来我们就来介绍一下如何在Javascript中定义类似Java这样的语言中的类和对象,如何定义共有的成员变量(属性)和方法,如何定义私有的成员变量和方法,如何定义类级别的变量和方法(也就是类似于Java中的静态属性和静态方法)。

115 AJAX技术核心 定义类: 定义对象: public class Book{ Book myBook = new Book();
public String name; public Book(){ } public void setName(String name){ this.name = name; public String getName(){ return this.name; 定义对象: Book myBook = new Book(); 调用对象的方法: myBook.getName(); 调用对象的属性: myBook.name;

116 AJAX技术核心 我们看到在Java中我们定义一个类使用class关键字,我们定义的类有类名,在类中我们有一个构造方法,我们还在类中定义了一个公有的成员变量(当然通常情况下从封装的角度来说成员变量我们通常会做成私有的)以及两个操作成员变量的成员方法。 定义对象的时候我们使用的是new操作符来新建对象,调用方法的时候,我们使用的是点加上方法名的方式,调用对象属性的时候(也就是访问类中定义的成员变量)我们使用了点加上属性名。

117 AJAX技术核心 那么现在我们想在Javascript中也有类似的方式来建立类和对象,怎么做呢?
第一步我们也来定义一个类。首先请注意,Javascript中是没有类这个概念,我们在Javascrip中随处可见的函数(function)其实是类似于Java这样的语言中的类结构的。回想在Java中,我们的类有变量和方法,在Javascript中我的一个函数中也可以有变量和方法(这里的方法在Javascript中仍然可以写成一个function)的定义。既然如此,我们就可以用一个function来实现我们在Javascript中的“类”梦想。

118 AJAX技术核心 Java中类定义有关键字,有类名。Javascript中我们也期望这样,那Javascript中的类关键字是什么呢?答案肯定是没有的,因为Javascript本身并没有类,但是我们可以把function看作是类的关键字。那类名呢?方法名就可以作为类名。那么先来定义一个没有属性和方法的Javascript类吧,注意Java中处于规范,我们的类名首字母都大写,这里我们也遵循这样的规范,如下所示: function Book(){ }

119 AJAX技术核心 一个最简单的类有了,那我们来用它创建对象吧,Java中我们用new操作符,Javascript中我们也有这个操作符,创建对象的方式如下所示。你会发现,这和在Java中创建对象的方式是一样的。 var book = new Book();

120 AJAX技术核心 function Book(name){ this.name = name;
目前来看我们的这个类和函数没啥差别,我们需要再做些工作让它看起来更像一个类而不是一个函数。我们来思考函数一般是什么样子的:里面有一些局部变量,还有多行程序流程(if,for,while等等),当然也会有调用别的函数的语句。那么类应该是什么样子的呢:应该有成员变量,有成员方法。那么好,为了让上面我们定义的这段内容更像是类,我们加入成员变量和成员方法。 加入成员变量和方法的Javascript类如下所示: function Book(name){ this.name = name; this.setName = function(name){this.name = name;} this.getName = function(){return this.name;} }

121 AJAX技术核心 注意这里我们的表示类的这个function多了一个参数,怎么理解这个参数呢?
想想我们在Java中一个类都有构造函数,构造函数是可以有参数的,那么我在创建类的对象的时候就可以使用有参数的构造函数。 那么,Javascript里面的这种类的定义方式,我们可以理解这个function即表示了类的定义,同时又是类的构造函数,当我们使用new操作符创建类的对象时,实际上会调用这个函数。

122 AJAX技术核心 我们还发现这里使用了this这个关键字。回想在Java中this的含义,它表示当前对象。那么在Javascript中,this的含义也是表示当前对象。 所以this.name = name这句话的作用实际上就是让当前建立的对象的name属性值是构造时传入的值。 同样的this.setName和this.getName两句话的定义是让当前建立的对象的setName和getName属性分别是两个匿名方法,这实际上就等于是定义了我们期望的成员方法。

123 AJAX技术核心 我们再来通过下面的代码看看如何建立对象和使用对象属性和方法: var book1 = new Book(“AJAX”);
var book2 = new Book(“Java”); alert(book1.name); //显示book1的name值,输出内容是AJAX alert(book2.getName()); //调用book2的getName方法显示name值,输出内容是Java book1.setName(“C#”);//调用book1的setName方法设置新的name值 alert(book1.getName());//调用book1的getName方法显示新的name值,输出内容是C#;

124 AJAX技术核心 Javascript中的对象和面向对象语言中的对象不同的一个地方是,Javascript这种动态语言允许动态的给一个对象增加属性。在Java中我们定义了属于某个类的一个对象,那么这个对象可使用的属性和方法是固定,但是在Javascript中我们通过类创建出来的对象则可以随时根据需要增加属性和方法,我们接着上面的代码再写出下面的内容: book2.author=”wang”;//给book2对象动态增加一个新的属性 alert(book2.author);//显示author属性值,输出内容是wang book2.setAuthor = function(author){this.author = author};//给book2对象动态增加一个新的方法 book2.setAuthor (“zhu”); //设置author属性的新值 alert(book2.author);//显示新的author值,输出内容是wang

125 AJAX技术核心 最后,我们再来看一下在Javascript当中另一种定义类的方式,我们仍然定义和上面一样的Book类,定义方式如下:
var Book = function(name){ this.name = name; this.setName = function(name){this.name = name;} this.getName = function(){return this.name;} }

126 AJAX技术核心 发现这种方式和之前方式的差别了吗,类里面定义属性和方法是一样的,但是最外层的定义方式不一样了,语句的直接含义是我们定义了一个变量Book,然后让这个Book变量等于一个匿名的函数,函数有一个name的参数。为什么可以这么做呢?这是Javascript灵活性的一种体现。 经典的《Thinking In Java》中曾经说Java中一切皆对象。在Javascript中,我们不妨套用出一句类似的话:“一切皆变量”。 没错,我们说了Javascript是无类型的语言,因此不管是字符串,数字,数组,对象,函数都可以用一个var变量来表示。因此在这种定义方式中,我们实际上是先定义了一个“匿名类”(匿名方法),然后又给这个匿名类起了一个名字。这里类名就是var后面的那个变量名了。

127 AJAX技术核心 这种方式和前面我们使用的类定义方式除了写法上有些差别以外,定义出的类在使用上是没有差别。我们可以根据喜好选择其中一种形式来定义类。 不过如果你希望区分你的类和普通函数的话,除了函数名大写表示类以外,采用我们介绍的第二种方式应该更容易让别人看出你想定义一个类。

128 AJAX技术核心 上一小节我们介绍了如何在Javascript中定义类和对象。我们会发现,我们定义类的成员变量和成员方式实际上都是在“构造函数”中定义并且赋值的。 而我们在Java中,构造函数一般只负责初始化成员变量,而成员变量和成员方法的定义都是在构造函数之外的。 那么在Javascript中,我们是否也可以这么做呢?答案是可以的,我们需要使用prototype这个特殊的属性。

129 AJAX技术核心 在Javascript中的定义的每一个函数都有一个prototype的属性,这个属性表示的是一个叫做原型对象的内容。原型对象的作用是当我们给它定义一个属性时(这个属性即可以表示一个成员变量,也可以表示一个成员方法),拥有这个原型对象的函数表示的类所创建出来的对象可以使用原型对象中定义的属性。举例如下: Book.prototype.print=function(){alert(“name: ” + this.name);} var book3 = new Book(); book3.print(); Book.prototype.hello=function(){alert(“Hello”);} book3.hello();

130 AJAX技术核心 当我们给原型对象增加一个print方法以后,Book类的对象book3就可以使用这个方法了。而且在book3这个对象已经建立以后,如果我们再给原型对象增加一个hello方法,book3对象仍然可以使用hello方法。

131 AJAX技术核心 我们用prototype的方式再来定义一下Book类: var Book = function(name){
this.name = name; } Book.prototype.getName =function(){return this.name;} Book.prototype.setName =function(name){this.name = name;}

132 AJAX技术核心 我们用prototype的方式再来定义一下Book类: var Book = function(name){
this.name = name; } Book.prototype.getName =function(){return this.name;} Book.prototype.setName =function(name){this.name = name;} 这时我们发现,我们已经学习了两种定义类成员变量和成员方法的方式,那么这两种方式有什么差别呢?使用那种更好呢?我们来看下面张图:

133 Prototype

134 AJAX技术核心 从上图中我们可以发现“构造函数”法来定义成员变量和成员方法,我们在创建对象时,就会把“构造函数”中的内容都创建出来,假设一个成员变量占用一个内存单位,一个成员方法占用两个内存单位,那么我们每创建一个对象,其中都保存着name变量,setName,getName方法,这个对象将占用了五个内存单位,四个对象我们使用了二十个内存空间。 而如果我们使用本节的prototype方式定义类,那么成员方法都保存在原型对象中,由于一个类只有一个原型对象(实际上是表示类的那个函数只有一个原型对象),所有这个从这个类创建出来的对象都继承(也可以说是共享)了原型对象中定义的两个方法,这时我们每创建一个对象,实际上对象中只保存了成员变量name,同时继承使用原型对象中的setName和getName方法,四个对象我们将只占用4*1+4=8个内存空间。

135 AJAX技术核心 Book.prototype.tt = "zxc"; var book1 = new Book("AJAX");
到这里两种方式的优劣就显而易见了,prototype的方式在节省资源方面非常有优势。但是请注意,原型对象中适合保存成员方法和常量,但不适合保存普通的成员变量。这是为什么呢?我们在本章建立的Book类的基础上加几行代码,来看下面这个例子: Book.prototype.tt = "zxc"; var book1 = new Book("AJAX"); var book2 = new Book("Java"); alert(book1.tt); alert(book2.tt); book2.tt = "bnm";

136 AJAX技术核心 你觉得这个程序的输出结果会是什么呢?前两次alert我们都能想到,肯定是”zxc”,第三个我们也能想到,输出”bnm”,第四个是不是也是”bnm”呢?不,第四个还是”zxc”。为什么会这样呢? 这是因为原型对象中定义的内容对于它所属于的那个类创建出来的对象们来说是只读的。你可以用点加上原型对象中定义的那个属性名来取到属性值,但是当你用点加上原型对象中定义的那个属性名给那个属性赋值时,实际上并不是在给原型对象中的属性赋值,而是在给你的这个对象动态增加一个属性,这个属性的名字和原型对象中的那个属性名一样。下面这个图很好的描述了对象内部的变化以及alert时对象到底读取了哪个tt属性。

137 Prototype

138 AJAX技术核心 Book.prototype.tt = "bnm" 当然如果你想改变原型对象中定义的属性值,就只能像下面这样的方式来做:
这个时候,所有本身没有tt属性的对象再来读tt这个属性的时候,值就变成了”bnm”了。有人会说那我用book1.prototype.tt这种方式是不是可以修改属性呢?实践是回答问题最好的方法,我们可以运行一下这行代码,你会发现,会有错误产生,那是因为只有一个表示函数的变量才有prototype属性,才有原型对象,而对于一个普通对象来说,它是没有prototype属性的。

139 AJAX技术核心 我们知道了普通的成员变量不适合定义在原型对象中,我们再来总结一下为什么方法和常量适合定义在原型对象中。
我们使用方法其实都是一个读操作,而且不同对象使用同一个方法可以产生不同的运行结果,之间互不影响。 至于常量,常量是不会变的,它的作用就是给别人读的,既然原型对象中的属性只是用来读的,那么常量放在原型变量里面定义就非常合适了。 因此原型对象中定义一份方法或常量都是既省空间又不影响使用,何乐而不为呢?

140 AJAX技术核心 现在我们来总结一下吧,为了写一个“完美”的Javascript类,我们应该遵循如下守则:
用prototype方式,比较适合定义成员方法 用prototype方式,比较适合定义一个类的常量,例如我们需要一个Book类的常量间作TYPE,那么可以使用下面的定义方式。注意,一个良好的习惯是把你定义的常量想Java中一样用全大写字母,这样别人也比较容易阅读。 Book.prototype.TYPE = “Class”;

141 AJAX技术核心 本节最后我们再花一点时间讨论一下Javascript中的“继承”。
前面我们说了,prototype方式定义的常量和方法保存在原型对象中,这个原型对象所属于的类创建出来的对象都“继承”了原型对象中定义的内容。 回想一下我们熟悉的Java,Java中我们也有继承,一个子类继承一个父类,子类的对象可以使用父类所有的共有和保护的成员变量和方法。 对比一下,虽然两种语言中我们都以“继承” 这个字眼来描述这个父子关系,但是我们需要注意,两种语言的“继承”差别还是很大的。

142 AJAX技术核心 Java中父类可以有子类,子类可以再有自己的子类,继承关系可以很深。而在Javascript中,所谓的“继承”仅仅是一个类(实际上是函数)的所有对象可以继承原型对象的属性内容,不存在多层次继承的情况。 另一方面,Java中子类继承了父类的成员变量,那么每一个子类对象在是用这个成员变量时都是独立互不影响的,而在Javascript中,由于这个继承是对象之间的继承,且一个类的多个对象同时继承了这个类的一个原型对象,因此,当原型对象中的属性发生变化时,所有的普通对象在获取这个属性时也都会发生变化。 最后,Java中从父类继承的成员变量是可读可写的,而Javascript中,则是只读的,当你象写这个属性时,实际上并没有真正修改原型对象中的那个属性值,而是给当前对象新建了一个属性,如我们前面的例子所示。

143 AJAX技术核心 到目前为止我们在类中定义的属性和方法都是公有的,也就是说对象都可以直接访问到它们。我们知道在面向对象中我们经常需要封装一些数据,在Java中我们使用private关键字把它们变成私有的内容。在Javacript中我们同样会有这样的需求,那么如何在Javascript的类中定义私有的属性和方法呢?

144 AJAX技术核心 Javascript中并没有Java那样的关键字来控制属性方法的访问权限,因此我们只有采用曲线救国的方式来解决这个问题。我们知道所谓私有的内容就是在类之外是不可见的。Javascript中我们的类就是一个方法,那么什么内容在方法之外不可见呢?没错,就是方法中的局部变量。那么如果我们在方法中定义一个局部变量,那它就是我们Javascript类中的私有成员变量了。

145 AJAX技术核心 var Book = function(name){ var privateVale = 999;
问题还没有结束,我们需要有公有的方法让用户可以访问到私有的变量,好,按照我们上一节的思路,成员方法用prototype方式定义,那我们就这么定义两个方法来设置私有变量吧。我们还是在Book这个类的基础上修改,代码如下: var Book = function(name){ var privateVale = 999; this.name = name; } Book.prototype.getName =function(){return this.name;} Book.prototype.setName =function(name){this.name = name;} Book.prototype.setPrivateValue =function(value){this.privateVale = value;} Book.prototype.getPrivateValue =function(){return this.privateVale;} var book1 = new Book(“AJAX”); alert(book1.getPrivateValue());

146 AJAX技术核心 试着运行一下这段代码,你会发现没有达到你的预期,输出内容为undefine。我们那里错了呢?对了,privateValue不是对象的属性,他只是私有的局部变量,用this是找不到的,那我们修改一下去掉this如何: Book.prototype.setPrivateValue =function(value){privateVale = value;} Book.prototype.getPrivateValue =function(){return privateVale;}

147 AJAX技术核心 再次运行,我们发现还是undefine。。。。。。,错在那里了呢?我们对局部变量的理解还是有点偏差,既然privateValue是局部变量,那么在它所在的方法之外,它都不可见,当然原型对象中的方法就无法访问到这个变量了。看来想要访问这个私有变量,我们只能放弃通过prototype来定义我们的方法了,回到效率不好的“构造函数”方式来定义我们的方法。代码如下:

148 AJAX技术核心 var Book = function(name){ var privateVale = 999;
this.name = name; this.setPrivateValue =function(value){privateVale = value;} this.getPrivateValue =function(){return privateVale;} } Book.prototype.getName =function(){return this.name;} Book.prototype.setName =function(name){this.name = name;} var book1 = new Book(“AJAX”); alert(book1.getPrivateValue());

149 AJAX技术核心 现在我们再来运行这段代码,我们发现终于出现我们想要的结果999了。
同样的,如果你想定义私有方法,也可以采用类似的方式,代码如下:

150 AJAX技术核心 var Book = function(name){ var privateVale; this.name = name;
var setPrivateValue =function(value){privateVale = value;} this.getPrivateValue =function(){return privateVale;} setPrivateValue(999); } Book.prototype.getName =function(){return this.name;} Book.prototype.setName =function(name){this.name = name;} var book1 = new Book(“AJAX”); alert(book1.getPrivateValue());

151 AJAX技术核心 上面这段代码,我们定义了外部可见的公有方法getPrivateValue以及私有内部可见的setPrivateValue方法,这样对于私有属性privateVale,别人在使用的时候就只能获取它的值而不能给它赋值了。 我们来总结一下,当你需要定义Javascript中的私有变量和方法的时候,可以在“构造函数”中通过局部变量的方式来定义,注意提供给别人操作这些私有变量和方法的方法只能在“构造函数”中定义成公有,而不能在原型对象中定义,因为只有构造函数中才可以看到这些私有变量。

152 AJAX技术核心 我们在回到Java,想想Java的类中还有什么特性。对了。静态属性和静态方法。Java中的静态属性和静态方法都有一个static的关键字。 对于静态属性和静态方法,我们说它是属于类,而不是属于类的对象的。静态的内容我们在使用的时候不需要建立一个对象,直接通过类名点静态属性或方法名即可。

153 AJAX技术核心 那么,Javascript中我们是否也可以有静态属性和方法呢?很明显,从Javascript语言级的角度来说,它并没有Java那样的static关键字,也就不可能有语言级的静态属性和方法了,但是我们也可以让我们在Javascript中的类有静态的属性和方法。 Javascript中的类是一个函数,对于我们前面看到了每个函数都有一个prototype的属性表示它的原型对象。这说明函数是可以有属性的,既然可以有属性就可以动态的增加属性。所以当我们需要定义Javascript中的类的静态属性和方法时,就可以给表示类的变量增加属性内容。仍然以Book类为例,示例代码如下:

154 AJAX技术核心 Book.TYPE = “IT”; Book.print = function(){alert(Book.TYPE);}
如上所示,我们定义的“静态”属性和方法与Java中的使用方式一样,当然定义方式略有不同,Java中的都定义在类里面了,而javascript中我们一般定义在类构造函数的外面。 这里仍然有一个建议,就是类的“静态”属性名使用大写字母,这和前面说道的prprotype定义的常量一样,为的是让别人一目了然。这种类“静态”属性和prorotype定义的常量还是有一些差别的,一个类的所有对象看到的prototype定义的常量值是一样的,读变量的时候可以通过对象名点上变量名,但是不能写,而且可能存在对象中定义的属性覆盖了prototype中定义的这个常量。而类的“静态”属性在整个程序中看到的结果都是一样的,读写变量的时候都是类名点上变量名。

155 AJAX技术核心 在Javascript中应该在何时定义类的“静态”属性和方法。总的来说和Java中是一样的。当类的某个值与对象无关期望所有位置看到的结果是一样的时候,就可以定义为类静态属性。如果类的一个方法做的是和具体对象无关的操作,而是做一些工作操作的时候,就可以将这个方法定义为静态的类方法。

156 AJAX技术核心 我们已经学习了如何在Javascript中面向对象的编写程序,接下来我们想做的就是把前面讲过的XMLHttpRequest的使用面向对象化,自己来做一个XMLHttpRequest对象的封装。 我们为什么需要做封装呢?大家是否还记得本章第一节中我们学习使用XMLHttpRequest的那五个步骤,当我们每次使用XMLHttpRequest对象时,都要经历这五个步骤的洗礼,是不是很麻烦,很烦琐?

157 AJAX技术核心 还有,这五个步骤中还有很多问题需要注意,浏览器建立XMLHttpRequest对象的差异,GET方式和POST方式的差异,获取服务器返回值所需要做的判断工作,浏览器的缓存问题,跨域调用问题等等。很多问题都需要注意,如果那个问题没有处理好就会使我们的AJAX之旅变得不再畅通。 通常情况下我们做AJAX的应用,不想关心XMLHttpReuqest对象使用过程中的那一串事情,我们只希望把数据给XMLHttpRequest对象,让它帮我们异步的发出去,当数据回来的时候可以让我期望处理响应数据的方法工作就行了。问题摆在眼前了,怎么解决呢?

158 AJAX技术核心

159 AJAX技术核心 这段封装代码把之前我们提到的使用XMLHttpRequest需要注意的问题,以及像跨域,缓存这样的问题统统都封装了起来。这段代码中唯一需要说明的,也是和之前的未封装的代码有差别的就是设置回调函数的时候我们使用了匿名方法来直接定义回调函数,然后我们会在回调函数中根据响应情况调用用户提供的用于处理成功情况和用于处理失败情况的方法。

160 AJAX技术核心 这里有一个技巧,你可能注意到我们在send方法中定义了一个局部变量tempxmlhttp,让它等于了当前对象的xmlhttp属性,为什么要这么做呢? 还是为了满足我们的那个匿名回调方法。回想Java的AWT/SWING的图形界面程序中,我们经常会在一个方法内的通过在建立匿名对象的方式来设置事件,当我们建立匿名对象的时候,需要写一些匿名对象中必须有的方法,这个时候在匿名对象的方法中,我们可以访问到匿名对象所在方法的局部常量(final修饰的),但是我们无法访问当前对象的属性或方法,因为但我们使用this关键字的时候,它表示的不是我们期望的对象,而是被建立的匿名对象。 在Javascript中,匿名方法存在同样的问题,我们可以访问匿名方法所在的方法中的局部变量,但是不能访问当前对象的属性,因此我们定义了一个局部变量,以便于匿名回调方法可以取到xmlhttp的内容。 北京传智播客教育

161 AJAX技术核心 当我们使用这个封装的XMLHttpRequest时,你会发现原来我们写的那个校验用户名的例子,变得好写了很多,如下所示:

162 AJAX技术核心 var resultNode; function submit(){
resultNode = document.getElementById("result"); var xmlhttp = new MyXMLHttpRequest(); var name = document.getElementById("name").value; if(name == null || name == ""){ resultNode.innerHTML = "用户名不能为空"; return false; } xmlhttp.onreadystatechange=callback; xmlhttp.send("GET", " + encodeURI(encodeURI(name)),null,callback,failcallback); function callback(responseText,responseXML){ alert(responseText); alert(responseXML); resultNode.innerHTML = responseText; function failcallback(status,statusText){ resultNode.innerHTML = "服务器故障"; AJAX技术核心 北京传智播客教育

163 AJAX的优缺点 AJAX IFrame 代码意图清楚,明确。符合通常的编码思维方式 使用繁琐,逻辑不清楚
可以访问HTTP的Request,Response及状态码信息。由此可确定请求是否正确 不支持访问HTTP的相关信息 支持HTTP的所有传输方式,包括GET,POST 只支持HTTP的GET传输方式 XMLHttpRequest理论上不能存取跨域数据,但IE浏览器在访问跨域数据时会给出提示让用户选择,如果用户选择“是”,则会访问跨域数据。 支持跨域存取数据

164 AJAX的优缺点 AJAX IFrame 发送给服务器的数据以及从服务器接收的数据即可以是纯文本(包括HTML),也可以是XML数据
与服务器交互的数据只能是纯文本 浏览器无法保存历史信息,浏览器的向前向后按钮失效 浏览器可以保存历史信息,支持向前向后的网页跳转 对于IE浏览器,如果用户禁用ACTIVEX控件,则无法使用XMLHttpRequest 不存在这个问题。 对浏览器版本和类型有一定的依赖,不支持较早版本的浏览器,且不同浏览器上的实现存在差异。 对各种版本的浏览器都可以支持,且不同浏览器上不存在实现差异。

165 AJAX的优缺点 AJAX Flash 可被搜索引擎收录信息,便于用户通过搜索引擎找到站点信息。 搜索引擎收录信息效果相对较差 开发环境免费
开发环境昂贵 技术细节完全开放,有统一标准支持 技术细节并非完全开放,且受Macromedia的license协议限制,对于某些企业使用上带来不便 有浏览器兼容性问题,且不同浏览器实现方式不同 MacroMedia制定标准,在不同浏览器上不存在兼容性问题

166 AJAX的优缺点 AJAX Flash 不存在被拦截的问题。
目前很多软件的拦截网页广告的功能会将页面上的Flash内容拦截,导致Flash内容无法显示 声音图像元素的处理依赖于HTML本身的能力,相对较弱 处理声音和图像元素更有优势 不可以访问机器资源 可以访问机器资源,包括很多外部设备,带来方便的同时也带来了安全上的隐患。 流媒体支持不好 可以很好的支持流媒体 手持设备对AJAX支持不好 在手持设备上可以很好的支持

167 综合实例-学生信息管理系统: submitButton.setAttribute("disabled", true); submitNode.removeAttribute("disabled"); submitButton.onclick = function () { submitStudent(uniqueID); }; oralData.unshift(……)

168 综合实例-学生信息管理系统: {id:id,name:oralName,number:oralNumber,classname:oralClassName} oralData.splice(index,1);

169 综合实例-动态股市信息: setTimeout(code, delay) clearTimeout( ); setInterval(code, interval) clearInterval( )

170 综合实例-提示框: onmouseover="show(this,event) onmouseout="clearinfo()“ if(!env){ myEvent = window.event; } else{ myEvent = env; }

171 综合实例-提示框: mouseX = myEvent.clientX; mouseY = myEvent.clientY; divNode.style.left divNode.style.top “px”

172 综合实例-简易的google suggest:
onkeyup="completeText(event)“ keyCode = myEvent.keyCode; keyCode表 ,

173 综合实例-简易的google suggest:
var left = textNode.offsetLeft; var tmp = textNode.offsetParent; while(tmp){ left += tmp.offsetLeft; tmp = tmp.offsetParent; } tipNode.style.left = left + "px";

174 综合实例-简易的google suggest:
使用对象直接量传递数据 var tipArray = eval(responseText);

175 综合实例-简易的google suggest:
tdNode.onmousemove = function(){ this.style.backgroundColor = "red"; }; tdNode.onmouseout = function(){ this.style.backgroundColor = "#FFFAFA";}; tdNode.onclick = function(){ textNode.value = this.firstChild.nodeValue; clearTbody();};

176 WebService WebService是可以供任何程序通过网络访问的一种服务。 最大的优势是跨平台的可互操作性
SOA(Service-Oriented Architec-ture ) 面向服务的架构

177 WebService SOAP(Simple Object Access Protocol )分布式环境中交换信息的轻量级协议
Binding Style: RPC 、Document Encoding styles Literal、encoding

178 WebService Literal :SOAP消息中只有数据没有数据类型。这种方式是开发包相关的,没有什么标准;如<x>50</x>,单从SOAP消息,你无法判断50是数字还是字符串,而具体的类型可以在开发包将SOAP请求映射到具体的Service类时来确定并完成转换,对于返回值也一样,客户端可以通过SetReturnValueType(...)之类的方法告知开发包自己期待什么类型 Encoding就是在SOAP消息中携带类型信息,并且依据某种规则将数据编码传递,接收端可以根据类型信息和编码规则完成解码,获得原始数据;如<x xsi:type="xsd:string">50</x>

179 WebService RPC就是按照类似函数调用时所需的信息来组装SOAP消息:操作名作为根元素,参数组成子元素
<envelope><body> <myMethod> <x>5</x><y>8</y> </myMethod> </body></envelope> (RPC/Literal) <x type=string>5</x><y type=int>8</y> </body></envelope>  (RPC/Encoded)

180 WebService Document 就是将SOAP请求和响应,或者说输入输出定义为XML元素,有严格的Schema(“document” style means the messages in and out of the service are exactly as they are describe by the XML Schema in the WSDL).如某个Web Service的WSDL片断

181 WebService <types>     <schema>         <element name="xElement" type="xsd:int"/>     </schema> </types> <message name="myMethodRequest">     <part name="x"    element="xElement"/> </message> <message name="empty"/> <portType name="PT">     <operation name="myMethod">         <input message="myMethodRequest"/>         <output message="empty"/>     </operation> </portType>

182 WebService 则对应的SOAP消息如下: <soap:envelope>     <soap:body>         <xElement>5</xElement>     </soap:body> </soap:envelope> 然而这种方式没有在SOAP消息中包含操作名,所以如果两个不同的操作具有相同的输入,开发包有可能无法决定把请求转发到哪个函数,为避免这种情况,开发包一般为每个操作的输入输出都产生具有唯一名称的Element,不管它们是否内容相同;或者作为开发者,你可以选择 Wrapped 风格

183 WebService Wrapped 风格就是定义与操作同名的Element,将参数作为 Child Element;这样操作名又重新回到了SOAP消息中,如WSDL片断:

184 WebService <types><schema>                 <element name="myMethod"/>             <complexType><sequence>                     <element name="x" type="xsd:int"/>                 </sequence></complexType>         </element></schema></types> <message name="myMethodRequest">     <part name="parameters" element="myMethod"/> </message> <message name="empty"/> <portType name="PT">     <operation name="myMethod">         <input message="myMethodRequest"/>         <output message="empty"/>     </operation> </portType>

185 WebService 对应的SOAP消息: <soap:envelope>     <soap:body>         <myMethod>  <x>5</x>   </myMethod>     </soap:body> </soap:envelope> 这种方式也具有明显的弱点:无法方便的处理重载,因为XML Schema不允许定义相同名称的元素;这样,即使你的后台编程语言支持函数重载,你也应该尽量避免使用

186 WebService 开发WebService: JDK6: XFire:

187 WebService AJAX连接WebService
xmlhttp.setRequestHeader("Content-Type","text/xml"); xmlhttp.setRequestHeader("SOAPAction",soapAction);

188 WebService xmlhttp.send("<SOAP-ENV:Envelope xmlns:SOAP-ENV=\" " + "xmlns:SOAP-ENC=\" " + "xmlns:xsi=\" " + "xmlns:xsd=\" + "<SOAP-ENV:Body>" + "<m:sayHello xmlns:m=\" + "<in0 xsi:type=\"xsd:string\">wangxingkui</in0>" + "</m:sayHello ></SOAP-ENV:Body></SOAP-ENV:Envelope>");


Download ppt "AJAX技术入门."

Similar presentations


Ads by Google