AJAX是高性能JavaScript的基础。
它可以通过延迟下载体积较大的资源文件来使得页面加载速度更快。
它通过异步的方式在客户端和服务端之间传输数据,从而避免页面资源持续不间断(一窝蜂)地下载。
它甚至可以只用一个HTTP请求就获取整个页面的资源。multipart XHR
选择合适的传输方式和最有效的数据格式,可以显著改善用户和网站的交互体验。
1. XMLHttpRequest
获取通用的XHR对象,并进行数据请求与获取
/** * 创建通用的XHR对象 */ function createXHR() { var msxml_progid = [ 'MSXML2.XMLHTTP.6.0', 'MSXML3.XMLHTTP', 'Microsoft.XMLHTTP', //不支持readyState 3 'MSXML2.XMLHTTP.3.0' //不支持readyState 3 ]; var XHR = null; try { XHR = new XMLHttpRequest(); }catch(e) { for(var i=0,j=msxml_progid.length; i<j; i++){ try { XHR = new ActiveObject(msxml_progid[i]); break; //如果上面的语句有错直接跳到catch子句中,正确的话直接跳出循环 }catch(e2) {} } }finally { return XHR; } } function request() { var xhr = createXHR(); var url = 'index.php'; xhr.open('get', url, true); //设置请求头消息 在服务器端判断是否是AJAX请求$_SERVER[‘HTTP_X_REQUESTED_WITH’] xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.setRequestHeader('anan', 'mackxu'); xhr.send(null); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { if(xhr.status==200 || xhr.status==304) { response(xhr.responseText); } } } } //处理服务器响应的数据 function response(sData) { document.getElementById('response').innerHTML = sData; }
使用XHR时,POST和GET的对比:
Get方式:
用get方式可传送简单数据,但大小一般限制在1KB下,数据追加到url中发送。另外最重要的一点是,它会被客户端的浏览器缓存起来,那么,别人就可以从浏览器的历史记录中,读取到此客户的数据,比如帐号和密码等。因此,在某些情况下,get方法会带来严重的安全性问题。
Post方式:
当使用POST方式时,浏览器把各表单字段元素及其数据作为HTTP消息的实体内容发送给Web服务器,而不是作为URL地址的参数进行传递,使用POST方式传递的数据量要比使用GET方式传送的数据量大的多。
总之,GET方式传送数据量小,处理效率高,安全性低,会被缓存,而POST反之。
使用get方式需要注意:
1 对于get请求(或凡涉及到url传递参数的),被传递的参数都要先经encodeURIComponent方法处理.
使用Post方式需注意:
1.设置header的Context-Type为application/x-www-form-urlencode确保服务器知道实体中有参数变量.
2.参数是名/值一一对应的键值对,每对值用&号隔开.如 var name=abc&sex=man&age=18
3.参数在Send(参数)方法中发送,
XHR的优点和缺点:
2. 动态脚本注入JSONP
能跨域请求数据
只能使用GET请求
对请求的完成情况无知直到回调函数执行或者不执行
响应消息作为脚本标签的源码,它必须是可以执行的JavaScript代码
将回调函数的名称作为传递服务器动态页面的数据之一
服务器端代码: <?php header("Content-type:text/javascript; charset=utf-8"); $callback = $_GET['callback']; //获取js回调函数名称 $data = '动态加载脚本数据'; echo $callback."('$data');"; JS代码: //动态脚本加载 function requestInfo() { var oScript = document.createElement('script'); oScript.type = 'text/javascript'; //把回调函数作为数据传递给服务器 oScript.src = "index.php?callback=displayInfo"; oScript.onerror = errorHandle; //当src有误时触发 //document.head.appendChild(oScript); //IE7/8不支持 document.getElementsByTagName('head')[0].appendChild(oScript); } //显示从服务器端获取的数据 function displayInfo(data) { document.getElementById('response').innerHTML = data; } function errorHandle() { //处理请求失败情况 }
3. Multipart XHR
MXHR允许客户端只用一个HTTP请求就可以从服务器端向客户端传送多个资源。
思路:通过在服务器端将资源(css文件/js文件/HTML片段/base64编码的图片)打包成一个由双方约定的分隔符分割的长字符串,发送给客户端。然后用JS代码处理这个长字符串,并根据它的mime-type类型和传入的其他“头信息”解析出每个资源。
图片资源 data:[<mime-type>][;base64],<data>
服务器端代码: //读取图片并将它们转换成base64编码的字符串 $img_dir = dirname(__FILE__).'/../images/'; //echo $img_dir; $images = array('password.gif', 'username.gif', 'warning.gif' ); $img_load = array(); //echo file_get_contents($img_dir.$images[0]); foreach ($images as $image) { $file_name = $img_dir.$image; $img_fh = fopen($file_name, 'r'); //读取图片 $img_data = fread($img_fh, filesize($file_name)); fclose($img_fh); $img_load[] = base64_encode($img_data); } //把图片字符串合并成一个长字符串,然后输出 $delimiter = chr(1); echo implode($delimiter, $img_load); 客户端JS代码: //MXHR一次请求多张图片 function request_imgs() { var oXHR = new XMLHttpRequest(); var url = '../test/index.php'; oXHR.open('GET', url, true); oXHR.send(null); oXHR.onreadystatechange = function() { if (oXHR.readyState == 4) { if(oXHR.status==200 || oXHR.status==304) { split_images(oXHR.responseText); } } } } //分割图片字符串,向页面动态添加图片 function split_images(sData) { var aImages = sData.split('\u0001'); var oImage = null; for(var i=0, len=aImages.length; i<len; i++) { oImage = document.createElement('img'); //创建image元素 //img.src = 'data:'+mimeType+';base64,'+data; oImage.src = 'data:image/gif;base64,'+aImages[i]; document.body.appendChild(oImage); } }
此技术的优缺点:
- 以这种方式获取的资源不能被浏览器缓存。
- IE6、7不支持readyState=3状态和data:.
- 可以减少HTTP请求数量,特别是页面包含大量其他地方用不到的资源尤其是图片资源
4. Beacons图片信标
用JS修改图片的src属性实际上是向服务器发送一个针对该图片的请求,同时也提供了一个向客户端返回数据的机会。
事件判断是否请求完成:onload、onerror
根据图片大小判断请求情况:成功,1X1,失败2X1 其他3X1...
function createImage() { var oImg = new Image(); //加载成功 oImg.onload = function() { //... }; //加载失败 oImg.onerror = function() { //... } oImg.src = '../images/username1.gif'; //指定要请求的文件的路径 }
图片和cookie
cookie在性质上是绑定在特定的域名下的。当设置一个cookie后,再向创建它的域名发送请求时,都会包含这个cookie,这个限制确保了存储在cookie中的信息只能让批准的接受者访问,无法被其他域访问
cookie的限制:
- 单个cookie的尺寸大小限制4096字节(加减1)
每个域在用户机器上cookie数量有限制(IE7+ 50个)
function createImage() { var oImg = new Image(); var oResponse = document.getElementById('response'); oImg.onload = function() { //根据约定获取cookie值 var name = getCookie('name'); deleteCookie('name'); oResponse.innerHTML = name; }; oImg.onerror = function() { oResponse.innerHTML = 'this is a error!!'; } oImg.src = '../test/index.php'; } //获取特定的cookie值 function getCookie(sName) { sName = encodeURIComponent(sName); //对Chrome有问题 var sRE = "(?:;)?"+sName+"=([^;]*);?"; var oRE = new RegExp(sRE); if (oRE.test(document.cookie)) { return decodeURIComponent(RegExp["$1"]); }else { return null; } } function deleteCookie(sName) { document.cookie = encodeURIComponent(sName)+"=0; " +"expires=Thu, 1 Jan 1970 00:00:00 UTC; path=/"; } 服务器端(PHP): <?php header("Content-type:image/gif"); //图片和cookie传递数据 setcookie('name', 'mackxu'); header("Location: ../images/username.gif");
优点和缺点:
- 很好的兼容性(跨浏览器)
- 请求执行成功和失败会有一些提示
- 可以跨域发送请求(对比XHR)
- 图片只能发送GET请求,发送的数据受限制,使用cookie返回数据也数据大小受限制、不安全