原生JS实现Ajax操作

1. XMLHttpRequest对象

在IE7以下的浏览器,不支持原生XHR对象,需要使用MSXML库中的XHR对象,有三种不同版本: MSXML2.XMLHttp、MSXML2.XMLHttp.3.0 和 MXSML2.XMLHttp.6.0。

如果要兼容这些浏览器,必须创建一个函数来处理兼容问题。

function createXHR(){
	if (typeof XMLHttpRequest != "undefined"){
		return new XMLHttpRequest();
	} else if (typeof ActiveXObject != "undefined"){
		if (typeof arguments.callee.activeXString != "string"){
			var versions = [ "MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"], i, len;
			for (i=0,len=versions.length; i < len; i++){
				try {
					new ActiveXObject(versions[i]);
					arguments.callee.activeXString = versions[i];
					break;
				} catch (ex){
					//跳过
				}
			}
		}
		return new ActiveXObject(arguments.callee.activeXString);
	} else {
		throw new Error("No XHR object available.");
	}
} 

然后就可以使用var xhr = createXHR();来在所有浏览器中创建XHR对象了。


2. XHR的用法

2.1 get请求

使用XHR对象,要调用的第一个方法是open()方法,用来初始化请求,接受三个参数,分别是请求类型、请求URL、是否异步发送请求。
xhr.open("get", "demo.php", true);

要发送get请求,必须接着调用send()方法:xhr.send(null);

由于是异步请求,需要检测一个状态,等待数据接收完毕再处理请求。这个状态通过readyState来表示。

readyState的值可以取0/1/2/3/4,分别代表未初始化、启动、发送、接受、完成状态。每次readyState改变都会触发事件: readystatechange

注意,为了保证跨浏览器兼容性,需要在open方法之前指定 onreadystatechange 事件。

var xhr = createXHR();
xhr.onreadystatechange = function(){
	if(xhr.readyState == 4){
		if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
			alert(xhr.responseText);
		} else {
			alert("Request was unsuccessful: " + xhr.status);
		}
	}
};
xhr.open("get", 'demo.php', true);
xhr.send(null);

对于get请求URL的查询字符串参数,可以使用encodeURIComponent来将参数转化为合法的URL。

function addURLParam(url, name, value){
	url += (url.indexOf("?") == -1 ? "?" : "&");
	url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
	return url;
}

2.2 post请求

get请求不同的是,post请求需要在send方法中,传入数据参数。还需要设置http请求头信息,将Content-Type设置为application/x-www-form-urlencoded

function submitData(id){
	var xhr = createXHR();
	xhr.onreadystatechange = function(){
		if (xhr.readyState == 4){
			if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
				alert(xhr.responseText);
			} else {
				alert("Request was unsuccessful: " + xhr.status);
			}
		}
	};
	xhr.open("post", "postexample.php", true);
	xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	var form = document.getElementById(id); // 将ID为id的表单中的数据序列化后发送给服务器
	xhr.send(serialize(form)); // 将表单数据序列化并发送
} 

serialize表单序列化函数:

function serialize(form){
	var parts = [],
	field = null,
	i,
	len,
	j,
	optLen,
	option,
	optValue;

	for (i=0, len=form.elements.length; i < len; i++){
		field = form.elements[i];

		switch(field.type){
			case "select-one":
			case "select-multiple":
			
			if (field.name.length){
				for (j=0, optLen = field.options.length; j < optLen; j++){ 
					option = field.options[j];
					if (option.selected){
						optValue = "";
						if (option.hasAttribute){
							optValue = (option.hasAttribute("value") ? option.value : option.text);
						} else {
							optValue = (option.attributes["value"].specified ? option.value : option.text);
						}
						parts.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(optValue));
					}
				}
			}
			break;

			case undefined: //字段集
			case "file": //文件输入
			case "submit": //提交按钮
			case "reset": //重置按钮
			case "button": //自定义按钮
				break;

			case "radio": //单选按钮
			case "checkbox": //复选框
				if (!field.checked){
					break;
				}
				/* 执行默认操作 */
			default:
				//不包含没有名字的表单字段
				if (field.name.length){
					parts.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value));
				}
		}
	}
	return parts.join("&");
}

3. GET请求和POST请求的区别

  1. GET请求的参数在URL中显示,数据通过URLcookie传输;POST请求的数据主要通过body传输。

  2. 使用GET请求发送数据长度有限制,POST请求发送数据量大。

  3. GET请求一般为了获取数据,POST请求一般是上传并修改数据。

  4. POST请求比GET请求更安全,数据在地址栏不可见。

3.1 使用GET请求需要注意的问题

  1. 注意安全性,不要把敏感信息的操作通过GET请求进行。

  2. 注意参数的大小,如果字节数过多,不适合GET请求。

  3. 注意防止XSS攻击及乱码问题,要对URL附带的参数字符进行统一编码处理。

  4. 注意缓存问题,GET请求会自动对数据进行缓存,有时候可能无法及时反映动态结果,可以附加上时间戳字符参数。

3.2 使用POST请求需要注意的问题

  1. 注意设置headerContent-Typeapplication/x-www-form-urlencode确保服务器知道实体中有参数变量。

  2. body中传递的参数数据也是key1=value1&key2=value2的形式。

  3. 如果是上传文件,需要设置Content-Typemultipart/form-data才能让服务器接收到二进制文件数据。

你可能感兴趣的:(JavaScript,Ajax)