1 / 42

Ajax 编程技术 第四章 Ajax 技术

Ajax 编程技术 第四章 Ajax 技术. 4.1 XMLHttpRequest 对象. 本章主要介绍技术是 XMLHttpRequest 对象,因为 Ajax 应用程序的中心就是它。同时,对于许多数网页开发的实际问题中,它也是最广泛适用的解决方案。 我们还将介绍该对象的 GET 和 POST 方法的使用。同时探讨用户使用此对象常见的错误,例如当试图让页面在所有服务器上都能运行时遇到的一些问题。 最后还介绍一种 Ajax 技术的替代方案及其示例。. 4.1 XMLHttpRequest 对象.

Download Presentation

Ajax 编程技术 第四章 Ajax 技术

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Ajax编程技术第四章 Ajax技术

  2. 4.1 XMLHttpRequest对象 本章主要介绍技术是XMLHttpRequest对象,因为Ajax应用程序的中心就是它。同时,对于许多数网页开发的实际问题中,它也是最广泛适用的解决方案。 我们还将介绍该对象的GET和POST方法的使用。同时探讨用户使用此对象常见的错误,例如当试图让页面在所有服务器上都能运行时遇到的一些问题。 最后还介绍一种Ajax技术的替代方案及其示例。 4-2

  3. 4.1 XMLHttpRequest对象 XMLHttpRequest对象最初是作为IE5中的一个ActiveX控件出现的,随后Mozilla 1.0、Netscape7、Safari1.2和Opera7.60都将它纳入自身。 XMLHttpRequest对象在IE浏览器和非IE浏览器中实现方法不同。 XMLHttpRequest对象的作用在于,允许用脚本程序通过HTTP连接到服务器,而不比通过HTTP请求响应模型与服务器通信。 4-3

  4. 4.2 创建XMLHttpRequest对象 • 创建XMLHttpRequest对象 • 在IE7、Firefox、safari和Opera中创建该对象的JavaScript代码为: var xmlRequet = new XMLHttpRequest(); • 在IE5/6中代码为: var xmlRequest = new ActiveXObject(“Microsoft.XMLHTTP”); 注意,JavaScript区分大小写,如果大小写不正确,什么东西都创建不出来。 使用XMLHttpRequest对象的方式有两种,同步和异步。 4-4

  5. 4.2 创建XMLHttpRequest对象 • 同步使用XMLHttpRequest对象 按照下面模式,可以同步地XMLHttpRequest对象: • 创建对象; • 创建请求; • 发送请求。 这种模式与传统模式没有区别,用处不大,真正强大的地方在于异步地使用它。 4-5

  6. 4.2 创建XMLHttpRequest对象 • 异步使用XMLHttpRequest对象 异步使用XMLHttpRequest对象时,必须使用onreadystatechange事件调用该对象。在触发该事件后,必须在应用程序采取行动之前检查readyState属性的内容,因此使用模式应该是: • 创建该对象; • 设置readystatechange事件触发一个指定的函数; • 检查readyState属性,看数据是否准备就绪。 • 如果没有准备好,隔一段时间再次检查。因为数据没有下载完时,我们无法使用它的属性和方法。 • 如果已经准备好,就继续往下执行; • 打开请求; • 发送请求。 readystatechange事件的整个操作都是在后台执行,这样就能够异步使用XMLHttpRequest对象。 4-6

  7. 4.2 创建XMLHttpRequest对象 • readyState属性 readyState属性指出了XMLHttpRequest对象在发送/接收数据过程中所处的几个状态。XMLHttpRequest对象会经历5种不同的状态。 • 0:未初始化。对象已经创建,但还未初始化,即还没调用open方法; • 1:已打开。对象已经创建并初始化,但还未调用send方法; • 2:已发送。已经调用send 方法,但该对象正在等待状态码和头的返回; • 3:正在接收。已经接收了部分数据,但还不能使用该对象的属性和方法,因为状态和响应头不完整; • 4:已加载。所有数据接收完毕 4-7

  8. 4.2 创建XMLHttpRequest对象 • XMLHttpRequest对象的属性和方法 4-8

  9. 4.2 创建XMLHttpRequest对象 4-9

  10. 4.2 创建XMLHttpRequest对象 • 使用XMLHttpRequest对象示例 此示例使用此对象网页的实现动态显示。页面上有几个链接,分别点击,可以显示不同的文字或图片,或者清除显示的文字或图片。下面是程序: 4-10

  11. 4.2 创建XMLHttpRequest对象 // index.htm <html> <meta http-equiv="Pragma" CONTENT="no-catch"> <meta http-equiv="Expires" CONTENT="-1" /> <head> <script type="text/javascript" src="XHRequest.js"></script></head> <body> Ajax实例展示 <table border=0 cellpadding=0 cellspacing=0 style="font-size:10pt;"> <tr><td align=center> <table border=0 cellpadding=2 cellspacing=0 style='font-size:10pt;' align=center> <tr> <td><a href="#" onclick ="sendRequest('Contacts');return false;">显示联系我们</a></td> <td><a href="#" onclick ="sendRequest('Calendar');return false;">显示日历时间</a></td> <td><a href="#" onclick ="sendRequest('Adverts');return false;">显示广告图片</a></td> </tr><tr> <td><a href="#" onclick ="sendRequest('delContacts');return false;">清除联系我们</a></td> <td><a href="#" onclick ="sendRequest('delCalendar');return false;">清除日历时间</a></td> <td><a href="#" onclick ="sendRequest('delAdverts');return false;">清除广告图片</a></td> </tr></table> </td></tr> <tr><td id="box1" height=60></td></tr> <tr><td id="box2" height=50></td></tr> <tr><td id="box3" height=50></td></tr> </table> </body> </html> 4-11

  12. 4.2 创建XMLHttpRequest对象 // XHRequest.js var xHRObject = false; if (window.XMLHttpRequest) { xHRObject = new XMLHttpRequest();} else if (window.ActiveXObject) { xHRObject = new ActiveXObject("Microsoft.XMLHTTP"); } function sendRequest(data) { if (data=='delContacts') { box1.innerHTML=''; } else if (data=='delCalendar') { box2.innerHTML=''; } else if (data=='delAdverts') { box3.innerHTML=''; } else { var bodyofrequest = getBody(data); xHRObject.open("POST", "display.php", true); xHRObject.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xHRObject.onreadystatechange = getData; xHRObject.send(bodyofrequest); } } function getBody(data) { var argument = "value="; argument += encodeURIComponent(data) return argument; } function getData() { if (xHRObject.readyState == 4 && xHRObject.status == 200) { var serverText = xHRObject.responseText; if(serverText.indexOf('|' != -1)) { element = serverText.split('|'); document.getElementById(element[0]).innerHTML = element[1]; } } } 4-12

  13. 4.2 创建XMLHttpRequest对象 <?php //display.php switch($_REQUEST['value']) { case 'Contacts': echo "box1|<br><b>Contacts</b><br>Anhui, Hefei,USTC"; break; case 'Calendar': $dt = gmdate("M d Y H:i:s"); echo "box2|<br><b>Calendar:</b><br> $dt"; break; case 'Adverts': $source = "logo.gif"; echo "box3|<br><b>Advert:</b><br><img src='$source '>"; break; case 'delContacts': echo "box1| "; break; case 'delCalendar': echo "box2|&nbsp;"; break; case 'delAdverts': echo "box3|&nbsp;"; break; } ?> 4-13

  14. 4.2 创建XMLHttpRequest对象 • 程序运行:运行初始状态入图1,点击链接后见图2: 图2 图1 4-14

  15. 4.3 常见错误 • 编程常见错误 • 企图通过双击网页文件运行它; • XMLHttpRequest大小写不正确; • 多写了对圆括号: 正确:xHRObject.onreadystatechange =getData; 错误:xHRObject.onreadystatechange =getData(); 必须弄清楚,在JavaScript中: • 函数名后如果有圆括号,意思就是将函数的返回值赋给等号左边的变量; • 没有圆括号,是将函数本身赋给等号前的变量。 4-15

  16. 4.3 常见错误 • 同源问题 XMLHttpRequest对象有些问题来自于同源问题。在较早版本的浏览器中,可以运行来自任何源的任何脚本,由此带来很严重的安全隐患。因此,处于安全的考量,“同源策略”被要求强制执行。即只有来自同一域、同一协议和同一端口的脚本才可以运行。 IE不检验它从XMLHttpRequest对象中取回的字段。其中的一个字段就是HTTPREFERER,它包含用户所浏览页面的URL/域名(注意:该字段的值并不总是一个)。 这意味着Referer完全可以在客户端进行伪造。IE这个的这个安全漏洞Referer值不可信。解决的办法之一是,我们可以在编写Cookie时,将域名/服务器添加到cookie中,以便验证发出的和接收的同源。 4-16

  17. 4.3 常见错误 • 缓存控制:IE主动缓存 为了节约带宽资源,浏览器会在本地缓存页面,然后从缓存中找出该页面而不是从源服务器下载页面。 这样一来,当页面更新后,可能页面并没有显示这种更新。解决的办法是,强制停止缓存。可以在网页中插入如下代码: <meta http-equiv=“Pragma” CONTENT=“no-catch” /> <meta http-equiv=“Expires” CONTENT=“-1” /> 这样足以使浏览器重载该页面。但如果使用XMLHttpRequest对象,且请求中包含GET指令,那么IE将始终缓存该页面,而决不会重载该页面。 4-17

  18. 4.3 常见错误 • 缓存问题的解决方法 我们有三种办法来解决缓存造成的问题。 • 在GET请求后添加querystring,并确保每次运行时, querystring值都不一样。将日期作为querystring值是一个好主意: xHRObject.open(“GET”,”display.php?id=“ + Number(new Date)+”&value=“ + data, true); 这种“每次输入不同的querystring值”的解决方法,从原理上将是一种回避策略。 4-18

  19. 4.3 常见错误 • 设置HTTP头部的If-Modified-Since为一个过期的时间: xHRObject.open=(“GET”, “display.php?value=“+data, true); xHRObject.setRequestHeader(“If-Modified-Since”, “Sat,1, Jan 2000 00:00:00 GMT”); 使用这种方法,可以阻止缓存。 • 使用POST 请求。我们将在下一节讨论这种方法。 一般来说,前两种方法用起来比较顺手,第3种方法可以完全避免缓存的困扰。 4-19

  20. 4.3 常见错误 • 跨浏览器兼容 在使用Ajax技术时,最困难的问题是让应用程序在不同的浏览器中都能够正常运行。实际上,这种想法非常不实际。 爱XMLHttpRequest应用中,用户使用的是IE还是Mozilla浏览器已成为次要问题,主要问题是创建哪个版本浏览器的XMLHttpRequest对象。我们需要注意以下问题: • ActiveX控件不能使用在IE之外的浏览器中; • 动态HTTPjihe document.all只能在IE上工作; • 在某些版本的Firefox上运行XMLHttpRequest会崩溃; • IE不区别大小写,而Mozilla却区别大小写; • 不同的IE版本,必须调用不同版本的MSXML。 • … 4-20

  21. 4.4 POST方法 使用POST方法替代GET方法,是另一种解决IE主动缓存页面的办法,它使Ajax技术提供一个更加无缝的前端。 将GET方法变成POST方法,除了需要做: • 将querystring删除; • 对发送的数据编码; • 将它作为跨服务器参数发送给send方法。该参数仍然是名/值,与querystring类似,格式为:value=Contents。但不附加在URL中,而是使用URL编码。 4-21

  22. 4.4 POST方法 • 如4.2节的示例中的POST方法: function sendRequest(data) { if (data=='delContacts') { box1.innerHTML=''; } else if (data=='delCalendar') { box2.innerHTML=''; } else if (data=='delAdverts') { box3.innerHTML=''; } else { var bodyofrequest = getBody(data); xHRObject.open(“POST”, “display.php”, true); //GET变为POST,删除querystring参数 xHRObject.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xHRObject.onreadystatechange = getData; xHRObject.send(bodyofrequest); } } function getBody(data) { var argument = "value="; argument += encodeURIComponent(data)//上传的数据编码,但变量名不编码 return argument; } 4-22

  23. 4.4 POST方法 • POST方法和GET方法的比较 • POST方法比GET方法传递的信息量大,最多可达2GB,而GET方法则大为减小,IE限制为2083个字符,Opera为4050个字符,Netscape4为8192个字符 • GET方法只能使用ASCII码传送且有缓存的困扰;而POST使用编码传送,且没有缓存的困扰。 • 如何选则 • 当查询的结果不会导致客户端页面变化,或下载量较小,使用GET方法; • 当查询的结果会导致客户端页面变化,或下载量很大时,用POST方法。 4-23

  24. 4.5 其他Ajax技术 • 动态脚本加载 可以用另一种不错的方法来替代XMLHttpRequest对象的使用。这就是动态脚本加载技术。 利用此技术,可以使用DOM动态创建JavaScript脚本,SRC属性也可以动态赋值。JavaScript源文件只在将其添加到页面时才下载并执行。 • 概念: • 添加脚本到页面; • 该脚本动态添加到另一个脚本到页面,并在后面附加SRC属性; • 脚本使用服务器启动对话框 4-24

  25. 4.5 其他Ajax技术 • 示例 示例中使用了一个脚本,根据用户选择,动态地创建其它3个脚本中的一个。 为了简捷,我们不使用服务器启动任何对话框,因为后面会介绍这种方法还有一些不足。 4-25

  26. 4.5 其他Ajax技术 • 创建一个名为ScriptLoader.htm的HTML页面: // ScriptLoader.htm <html xmlns="http://www.w3.org/1999/xhtml" > <head> <script type="text/javascript" src="ScriptLoader.js"></script> </head> <body> 你想加载哪个脚本?<br/> 脚本1<input id="range“ name="range" value="1" type="radio" onclick="retrieveInfo('1')" /><br/> 脚本2<input id="Radio1" name="range" value="2" type="radio" onclick="retrieveInfo('2')" /><br/> 脚本3<input id="Radio2" name="range" value="3" type="radio" onclick="retrieveInfo('3')"/><br/> </body> </html> 4-26

  27. 4.5 其他Ajax技术 • 创建名为ScriptLoader.js的脚本: // ScriptLoader.js function retrieveInfo(data) { var newScript = document.createElement("script"); newScript.src = "script" + data + ".js"; document.body.appendChild(newScript); } 4-27

  28. 4.5 其他Ajax技术 • 分别创建3个脚本,名为Script1.js, Script2.js, Script3.js //Script1.js alert ("加载了脚本1"); //Script2.js alert ("加载了脚本2"); //Script3.js alert (“这是脚本3"); 4-28

  29. 4.5 其他Ajax技术 • 现在运行ScriptLoader.htm文件,单击第二个按钮,程序运行结果如下图所示: 4-29

  30. 4.5 其他Ajax技术 • 说明 程序关键语句如下: var newScript = document.createElement(“script”); // 创建Script元素 newScript.src = “script” + data + “.js”; // 设置SRC 属性 document.body.appendChild(newScript); // 将新元素附加在body元素上 4-30

  31. 4.5 其他Ajax技术 • 评价 • 优点: • 可以使用多个不同的脚本,并按需加载不同的脚本; • 为我们提供了另一个创建服务器调用的机会。 • 缺点: • IE中动态加载脚本会停止其他所有的处理; • 只能使用GET方法,不能使用POST方法; • 往往不知道脚本是否得到真正的加载。 4-31

  32. 4.5 其他Ajax技术 • 图象和cookie • 工作方式 这种模式的工作方式如下: • <img>元素使用src属性封装请求,传递附加在querystring后的任何其他信息; • 服务器存储该信息,并编写存储在客户端cookie中的唯一可识别信息。 这种模式与动态脚本加载示例非常相似。但是没有动态脚本加载的缺点,它被广泛用于拥有大量电子邮件的用户,或者希望跟踪用户浏览习惯的网站。 4-32

  33. 4.5 其他Ajax技术 • 示例 网上售书页面。当用户查看该页面时,其正在浏览的页面的相关信息会作为图象的一部分发送到服务器,然后服务器会编写唯一的表示符到cookie,并使用消息框向用户显示该cookie中包含的信息。 4-33

  34. 4.5 其他Ajax技术 • 创建Cataloque.htm <html xmlns="http://www.w3.org/1999/xhtml" > <head> <script type="text/javascript" src="ImageLoader.js"></script> </head> <body onload="createImage()" style="font-size:10pt;"> <b>Book:</b><br/> <img id="cover" src="ajax.jpg" /> <br /><br /> <b>作者: </b><span id="authors"> 许富</span> <br /><b>ISBN: </b><span id="ISBN">97-7-123456</span> <br /><b>定价: </b><span id="price">50.20元</span> <img id="secret" src="onebyone.gif" /><br /><br /> <input type="button" onclick="showCookie()" value="查看cookie" /> </body> </html> 4-34

  35. 4.5 其他Ajax技术 • 创建ImageLoader.js脚本: function createImage() { var bookid = document.getElementById("ISBN").innerHTML; var img = document.getElementById("secret"); img.src = "relayInfo.php?bookid=" + bookid; img.width = 0; img.height = 0; } function showCookie() { var cookie = getCookieInfo("AnonymousID"); alert(cookie); } function getCookieInfo(cookie) { RegularXp = "(?:; )?" + cookie + "=([^;]*);?"; var RegularXpExtract = new RegExp(RegularXp); if (RegularXpExtract.test(document.cookie)) { return decodeURIComponent(RegExp["$1"]); } else { return null; } } 4-35

  36. 4.5 其他Ajax技术 • 创建relayInfo.php: <?php if ($_COOKIE[AnonymousID]) { $tempCookie = $_COOKIE["AnonymousID"]; setcookie("AnonymousID", $tempCookie."|BOOKID:".$_GET["bookid"], time()+3600); } else { $random_id = (rand()%9999999); $tempCookie = "USERID:" .$random_id."|BOOKID:" . $_GET["bookid"]; setcookie("AnonymousID", $tempCookie."|BOOKID:".$_GET["bookid"], time()+3600); } ?> 4-36

  37. 4.5 其他Ajax技术 • 运行结果 • 打开浏览器,运行首 文件Cataloque.htm, 见 右图。 • 点击“查看cookie”, 屏幕出现对话框,显示 Cookie信息 • 关闭浏览器,再次打 开,cookie信息被追加。 4-37

  38. 4.5 其他Ajax技术 • 示例说明 本例展示出,如何通过动态改变图象的scr属性来调用服务器。 • 在页面的开始部分加载了createImage,然后找到包含该图书ISBN的<span>元素中的内容(该书内容被存储在cookie中),以及Ajax.jpg图片 var bookid = document.getElementById(“ISBN”).innerHTML; var img = document.getElementById(“secret”); • 接着,使用指向服务器端页面和作为querystring传递的图书ISBN替换掉src属性。 img.src = "relayInformation.php?bookid=" + bookid; img.width = 0; img.height = 0; 4-38

  39. 4.5 其他Ajax技术 • 服务器端代码仅用来检查cookie是否存在。如果不存在cookie,则添加一个唯一的ID(本例中是一个随机数)和图书的ISBN号;如果存在cookie,则在cookie尾部添加上述信息。 if ($_COOKIE[AnonymousID]) { $tempCookie = $_COOKIE["AnonymousID"]; setcookie("AnonymousID", $tempCookie."|BOOKID:".$_GET["bookid"], time()+3600); } else { $random_id = (rand()%9999999); $tempCookie = "USERID:" .$random_id."|BOOKID:" . $_GET["bookid"]; setcookie("AnonymousID", $tempCookie."|BOOKID:".$_GET["bookid"], time()+3600); } 4-39

  40. 4.5 其他Ajax技术 • 然后使用showCookie()函数显示内容。在这里,Ajax技术快速得到匿名用户的查看模式。所以,利用该ID存储数据没有问题,然后就可以慢慢收集用户浏览习惯。 4-40

  41. 4.5 其他Ajax技术 • 评价 • 缺点: • 如果用户选择关闭图片下载,就没法运行; • Cookie存储信息有限制,大约是4KB; • 只能使用GET方法,不能使用POST方法。 4-41

  42. 4.5 其他Ajax技术 • 隐藏框架 • 原理:常使用此技术用于返回服务器信息。它采用带有两个框架的标准框架,打开两个独立的页面,第一个页面可见,第二个页面宽度和高度设置为0而变成隐藏不可见。隐藏框架用于发送请求和接收来自服务器的响应数据,但只在需要时才将接收的数据放在可见的框架中显示。 4-42

More Related