使用ajax中碰到的编码问题

在javascript中汉字的编码真是个很烦人的问题。js默认的是unicode编码,使用charAt函数返回的就是unicode16编码。其实要是只是unicode编码也没有什么,不知道为什么那些西方国家哪根筋不对,觉得unicode多字节字符用的少,只存储字母太浪费了,又搞出了utf-8这个编码。让我很有一种把这帮人暴打一顿的冲动。utf-8存储汉字要3个字节,就为了西方人使用字母存储少一个字节,我们就得多一个字节。而且关键就是这个utf-8搞的使用jquery中ajax功能汉字很容易碰到乱码的现象。看来谁掌握世界就是好,一切便利都由着他们的习惯。抱怨归抱怨,现实问题还是要解决的。
为了避免乱码,服务器和客户端要使用相同的编码,如果都是utf-8就不存在问题。单当服务器是gbk时,就会有问题,因为在jQuery的ajax提交的utf-8编码的数据。如果是get方法好解决,只要提前编码就可以了。post就很麻烦了因为在jQuery中提交参数时使用了encodeURIComponent这个函数,而这个函数返回值是使用utf-8的。如果不调用encodeURIComponent就不会有这个问题,网上有人写了这么一个函数替换jQuery.param方法
jQuery.param = function(a) {  
    var s = [];  
    function add( key, value ){  
        s[ s.length ] = escape(key,1) + '=' + escape(value,1);  
    };  
    // If an array was passed in, assume that it is an array  
    // of form elements  
    if ( jQuery.isArray(a) || a.jquery )   
        // Serialize the form elements  
        jQuery.each( a, function(){  
            add( this.name, this.value );  
        });  
    // Otherwise, assume that it's an object of key/value pairs  
	else 
        // Serialize the key/values  
        for ( var j in a ) 
            // If the value is an array then the key names need to be repeated  
            if ( jQuery.isArray(a[j]) )
                jQuery.each( a[j], function(){  
                    add( j, this );  
                });  
            else 
                add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );  
    // Return the resulting serialization  
    return s.join("&").replace(/%20/g, "+");  
}
这个只要在引用jQuery之后,使用ajax之前就可以了。修改后使用的是escape方法,这个转换的是unicode编码,现在的服务器可以自动识别。一般不会有乱码。如果怕服务器不能识别,那只能发送gbk编码的字符串。这就不能使用jQuery,只有用最基本的XMLHttpRequest来实现ajax,我做了如下示例:
function submitsql(){
	var xhr;
	if(window.XMLHttpRequest) {
		xhr = new XMLHttpRequest();
	} else if(window.ActiveXObject) {
		try {
			xhr = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (othermicrosoft) {
			try {
				xhr = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (failed) {
				xhr = false;
			}
		}
	} else xhr = false;
	if(xhr) {	
		xhr.onreadystatechange = function(){
			if(xhr.readyState == 4) {
				if (xhr.status==200) {// 200 = OK
					// ...our code here...
					eval("var result = " + this.responseText);
					var output = $("#exec_result");
					output.html("");
					var i,j,tt = "";
					if(result.title.length == 0) {
						if(result.error) {
							output.html("<p>执行["+result.result+"]错误: "+result.error+"</p>");
						} else {
							output.html("<p>成功执行["+result.result+"]</p>");
						}
					} else {
						for (i in result.title) {
							if(tt){
								tt = tt + " | " + result.title[i]
							} else {
								tt = "<p>" + result.title[i];
							}
						}
						tt = tt + "</p>";
						output.append(tt);
						for (i in result.records) {
							var rcd = result.records[i];
							tt = "";			
							for (j in rcd) {
								if(tt){
									tt = tt + " | " + rcd[j];
								} else {
									tt = "<li>" + rcd[j];
								}
							}
							tt = tt + "</li>";
							output.append(tt);
						}
					}
				} else {
					alert(this.responseText);
					//alert("Problem retrieving XML data");
				}		
			}
		}
		xhr.open("POST", "execresult.asp");
		xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		xhr.send("sqltext="+$("#sqltext")[0].value.urlEncode());
	}
}
其中的urlEncode()方法声明如下:
String.prototype.urlEncode = function() {
	var r = "";
	for (var i = 0; i < this.length; i++) {
		var chr =this.charAt(i) 
		var code = GetByteCode(chr);
		if (code.length > 2) {
			var b1 = code.substr(0, code.length - 2);
			var b2 = code.substr(code.length - 2);
			r += "%" + b1 + "%" + b2;
		} else {
			//!, ',(,),*,-,.,_,~,0-9,a-z,A-Z
			if(/!|\'|\(|\)|\*|\-|\.|_|\~|[0-9]|[a-z]|[A-Z]/.test(chr))
				r += chr;            	
			else if(code=="20")
				r += "+";
			else
				r += "%" + code;
		}
	}
	return r;
}
在这个函数申明中调用了GetByteCode函数,这是一个vbscript函数:
Function GetByteCode(ch)    
    GetByteCode = Hex(Asc(ch)) 
End Function
调用这个函数会对浏览器有很大的限制。可是万能的Javascript不支持读取字符串的实际编码,只好动用简陋的vbscript了。如果一定想实现可以通过查表的方法实现,不过那个会使文件变大。不知道你们有没有实现这个功能的javascript函数,反正我是没有的。这个方法还有一个缺陷就是修改了String对象原型方法,可能会产生一些难以预料的错误,比如遍历字符串实例的时候,可能会产生令人费解的异常。只能说javascript太强悍了,非一般人所能理解。
比较一下,还是决定采用了修改jQuery源码的方法,将param定义的原函数改为如下,并在ajaxSettings中加入charset:"utf-8",调用param时改为d.data=f.param(d.data,d.traditional,d.charset),这样就可以使用charset属性了。
function(a,c,i){typeof c=="string"&&(i=c,c=b);var d=[],h=function(a){return (i||f.ajaxSettings.charset)=="utf-8"?encodeURIComponent(a):escape(a,1);},e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=h(a)+"="+h(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bz,"+")}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值