我是靠谱客的博主 凶狠中心,最近开发中收集的这篇文章主要介绍前端开发涉及到的编码问题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言

URL只能使用英文字母、阿拉伯数字和某些标点符号,不能使用其他文字和符号。比如,世界上有英文字母的网址"http://www.abc.com",但是没有希腊字母的网址"http://www.aβγ.com"(读作阿尔法-贝塔-伽玛.com)。这是因为网络标准RFC 1738做了硬性规定:

"...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*'()," [not including the quotes - ed], and reserved characters used for their reserved purposes may be used unencoded within a URL."

"只有字母和数字[0-9a-zA-Z]、一些特殊符号"$-_.+!*'(),"[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL。"

这意味着,如果URL中有汉字,就必须编码后使用。但是麻烦的是,RFC 1738没有规定具体的编码方法,而是交给应用程序(浏览器)自己决定。这导致"URL编码"成为了一个混乱的领域。

如下:

1:地址栏输入和点击url访问浏览器时,chrome下无论请求地址和参数,均经过utf-8编码;非chrome浏览器,其中请求地址用utf-8编码,参数按操作系统编码进行编码(ie下的编码参数部分都不带%)。但参数中含特殊符号时,未确定何特殊符号会被编码。

例子:http://www.google.com/小明|=?param=小明|=
a.上面的url在中文xp的chrome下,发送的请求地址是

http://www.google.com/%E5%B0%8F%E6%98%8E%7C=?param=%E5%B0%8F%E6%98%8E|=

b.在中文xp的firefox下,发送的请求地址是
http://www.google.com/%E5%B0%8F%E6%98%8E%7C=?param=%D0%A1%C3%F7|= 

c.在中文xp的ie下,发送的请求地址是
http://www.google.com/%E5%B0%8F%E6%98%8E%7C=?param=С??|=

2:超链接中的请求,请求地址用utf-8编码,参数用页面编码,但是在ie下的参数不带%号。

在上面的例子中,在页面指定utf-8编码下,参数部分会变成:param=%E5%B0%8F%E6%98%8E|=。但ie会变成param=E5B08FE6988E|=。

3:js进行超链接访问时,和超链接情况一致。

4:ajax异步请求时,ie总是用gbk来编码,包括网页路径和参数,非ie和超链接请求一致。

在上面例子中,ie下发送的请求会变成:http://www.google.com/%D0%A1%C3%F7%7C=?param=d0a1c3f7|=

 

form提交涉及到的编码

 form 表单中有一个 accept-charset  属性,如果没有此属性会用页面编码来提交,如果页面编码没有就是 utf-8编码。

 

两个应用编码不同,一个是GBK编码,另一个是UTF-8编码。现在要在GBK编码的应用里使用表单向UTF-8编码的应用里提交数据,很显然,如果不做特殊处理的话,会出现乱码。 

解决方案:
在GBK编码的页面里编写如下代码: 
<form method="post" action="..." accept-charset="utf-8"> ... </form> 

如此的代码在Firefox等正常的浏览器下没有任何问题,但是遇到IE这个变态浏览器就不灵光了,我们还得用点不入流的手段Hack一下: 
<form method="post" action="..." accept-charset="utf-8" οnsubmit="document.charset='utf-8';"> ... </form> 

 

 

ajax 中涉及到的编码

ajax 提交到服务器的编码上面已经讨论过。但是获取后台内容也会有乱码的情况出现:

如果ajax 后台返回的不是utf-8的编码的二进制流,那么在xmlhttprequest 对象的responseText 方法中字符就会乱码,因为浏览器默认用utf-8来解码。 

我在后台返回时的conent-type 中也明确书写了charset :gbk 。但是实测没起到作用。 这个等有时间在验证

 

注意:

无论何种方式提交的服务器,浏览器都会转化成ascll字符,然后以ascll对应的码点转成二进制进行传输。对于那么不能直接转成ascll字符的,比如汉字。也会先用以上的编码方式转成ascll字符。
比如:
春节 ==》%E6%98%A5%E8%8A%82  utf-8编码
       ==》 %B4%BA%BD%DA            gbk 编码

在utf-8编码下,一个汉字 会有9个字节进行传输。

在一个html标签的属性中会有长度的限制。比如
a 标签的href 的长度限制,计算这个长度时要注意以上的细节

 

由于各个浏览器处理起来的不一致,所以我们需要用js来处理编码,因为js的处理结果都是一致的,都是utf-8编码。三个函数:

1.escape()

虽然这个函数现在已经不提倡使用了,但是由于历史原因,很多地方还在使用它,所以有必要先从它讲起。

实际上,escape()不能直接用于URL编码,它的真正作用是返回一个字符的Unicode编码值。比如"春节"的返回结果是%u6625%u8282,也就是说在Unicode字符集中,""是第6625个(十六进制)字符,""是第8282个(十六进制)字符。

  它的具体规则是,除了ASCII字母、数字、标点符号"@ * _ + - . /"以外,对其他所有字符进行编码。在u0000到u00ff之间的符号被转成%xx的形式,其余符号被转成%uxxxx的形式。对应的解码函数是unescape()。

 escape对0-255以外的unicode值进行编码时输出%u****格式,其它情况下escape,encodeURI,encodeURIComponent编码结果相同。

  所以,"Hello World"的escape()编码就是"Hello%20World"。因为空格的Unicode值是20(十六进制)

  首先,无论网页的原始编码是什么,一旦被Javascript编码,就都变为unicode字符。也就是说,Javascipt函数的输入和输出,默认都是Unicode字符。这一点对下面两个函数也适用。

  其次,escape()不对"+"编码。但是我们知道,网页在提交表单的时候,如果有空格,则会被转化为+字符。服务器处理数据的时候,会把+号处理成空格。所以,使用的时候要小心。可以这样处理下 str.replace(/+/g,"%u002B");

  escape不编码字符有69个:*,+,-,.,/,@,_,0-9,a-z,A-Z

 

2.encodeURI()

encodeURI()是Javascript中真正用来对URL编码的函数。
它着眼于对整个URL进行编码,因此除了常见的符号以外,对其他一些在网址中有特殊含义的符号"; / ? : @ & = + $ , #",也不进行编码。编码后,它输出符号的utf-8形式,并且在每个字节前加上%。
它对应的解码函数是decodeURI()。 需要注意的是,它不对单引号'编码。

 

3.encodeURIComponent()

最后一个Javascript编码函数是encodeURIComponent()。与encodeURI()的区别是,它用于对URL的组成部分进行个别编码,而不用于对整个URL进行编码。
因此,"; / ? : @ & = + $ , #",这些在encodeURI()中不被编码的符号,在encodeURIComponent()中统统会被编码。至于具体的编码方法,两者是一样。
它对应的解码函数是decodeURIComponent()。
encodeURIComponent不编码字符有71个:!, ',(,),*,-,.,_,~,0-9,a-z,A-Z

 

上面说到form post提交的时候可以设置 charset。那ajax提交的时候怎么办?比如怎么把上面三个函数处理过的utf-8编码的字符发送到GBK编码的后台

首先,当我们使用提交时,浏览器会根据当前页面编码,encode一次,然后发送到服务端,服务端接收到表单,会自动dencode一次,通常这个过程是对程序是透明的。即,浏览器把请求翻译成ascll字符传输,服务端接受二进制并翻译成ascll进行dencode。

这个dencode 和前端的encode 的编码不一致问题就来了。

解决:

1.使用escape函数 把中文换成%uxxxx的形式提交。这样浏览器encode的时候不会在处理了。到了后台,dencode完也是这种形式。 之后再用utf-8转一下。

2.

1.在A应用处用encodeURIComponent()2次编码参数数据,如k=中文(utf-8编码为%E4%B8%AD%E6%96%87),进行2次编码后,encodeURIComponent(encodeURIComponent(k))=%25E4%25B8%25AD%25E6%2596%2587

2.将请求发送到url2 = http://www.xxx.com/a.htm?k=%25E4%25B8%25AD%25E6%2596%2587&encoding=utf-8

3.url2对应应用收到这个请求后,web容器会对%25进行解码,变成%,对应request.getParameter("k")=%E4%B8%AD%E6%96%87

4.再URLDecoder.decode("%E4%B8%AD%E6%96%87", "UTF-8")就能解码回原来的中文而不会乱码了。

 

 

 

 

从编码到页面呈现中涉及的编码

我们在开发过程中新建文件(js,css,html),都会有默认的编码方式存储在硬盘上。不过的开发工具新建文件时的编码方式不同。

源代码发布到web容器后,用户在浏览器访问我们的文件,web容器以二进制流发送我们的文件给浏览器。

浏览器要解析这个二进制流。那么问题来了,浏览器用什么编码去解析?

1.根据http协议中的 content-type 中的charset ,content-type中的charset的优先级最高,如果有charset选项浏览器将忽略以下规则

2.html页面中meta标签中的charset。(js,css 也有charset ,如果有将用此charset ,如果没有就用宿主html的charset)

3.浏览器默认charset 

浏览器解析完这个二进制流之后,会把这些信息存在变量中。 变量在内存中存储的编码方式就是浏览器默认的了,跟以上的规则都没有关系了。 包括在html input 中输入字符都是浏览器以默认编码存储在内存中。

 

转载于:https://www.cnblogs.com/btgyoyo/p/6371516.html

最后

以上就是凶狠中心为你收集整理的前端开发涉及到的编码问题的全部内容,希望文章能够帮你解决前端开发涉及到的编码问题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部