URL 编码到底在编什么:百分号编码、中文转义与 encodeURIComponent 实战
讲清楚 URL 编码为什么存在,空格中文特殊符号怎么变成百分号编码,encodeURIComponent 和 encodeURI 区别在哪,以及查询参数该怎么安全拼接。
URL 编码到底在编什么:百分号编码、中文转义与 encodeURIComponent 实战
每个写过表单提交、拼过分享链接的人,迟早会撞上那串面目可憎的 %20%E4%BD%A0。它不是乱码,而是 URL 编码,也叫百分号编码(percent-encoding)。这篇把它讲透:为什么要编、哪些字符必须编、encodeURIComponent 和 encodeURI 区别在哪、查询参数怎么拼才不出事。
为什么 URL 里不能随便放字符
URL 设计之初只允许一小撮安全字符。按 RFC 3986 规定,URL 里能直接出现的只有非保留字符(A-Z a-z 0-9 以及 - _ . ~)和一组保留字符(: / ? # [ ] @ ! $ & ' ( ) * + , ; =)。保留字符各有语法含义:? 开始查询串,# 引出片段,& 分隔参数,= 连接键值。
问题来了。如果你的数据本身就含这些符号,比如活动名叫「夏季 & 秋季」,那个 & 会被浏览器当成参数分隔符,把你的值从中间劈成两半。空格更直接,URL 规范根本不允许裸空格出现。中文、emoji 这些超出 ASCII 范围的字符,URL 里压根没有它们的位置。
解决办法就是百分号编码:把不能直接放的字符,先转成它对应的字节,每个字节写成 % 加两位十六进制。空格变 %20,& 变 %26,= 变 %3D。这样数据就和 URL 语法彻底分开了。
中文和 emoji 怎么变成那串 %xx
ASCII 字符一个字符就是一个字节,转义很直观。但中文、日文、emoji 是多字节的,处理方式是:先按 UTF-8 把字符拆成字节,再把每个字节单独写成 %xx。
举个真实例子。汉字「你」在 UTF-8 下是三个字节 E4 BD A0,所以它编码后是 %E4%BD%A0。一个空格是 %20,emoji 😀 是四个字节,编码后是 %F0%9F%98%80。所以你看到一个汉字对应三段 %xx 是正常的,不是出错。
输入: 你 好
输出: %E4%BD%A0%20%E5%A5%BD
中间那个 %20 就是两个字之间的空格。想随手验证某段中文或符号编码成什么,可以直接用 URL 编码 / 解码工具 贴进去,正反都能跑,全程在浏览器本地完成,不上传。
encodeURIComponent 和 encodeURI 的关键区别
JavaScript 里有两个内置函数,选错一个就埋雷。
encodeURI 假设你传进来的是一整条 URL,所以它保留 URL 结构字符不动:: / ? # & = @ + 这些都原样留着。它只转那些一定非法的,比如空格和中文。适合给整条链接做最后兜底转义。
encodeURIComponent 假设你传进来的只是 URL 的一个零件,比如单个查询参数的值或一段路径。它把除字母数字和 - _ . ! ~ * ' ( ) 之外的全部转掉,连 & = ? / 都不放过。
这个区别在拼参数时性命攸关。看一个反例:
// 错误:用 encodeURI 编一个含 & 的参数值
encodeURI("a&b") → "a&b" 这个 & 会被当成参数分隔符
// 正确:用 encodeURIComponent
encodeURIComponent("a&b") → "a%26b" 这个 & 安全地属于值本身
记一句话就够:编整条 URL 用 encodeURI,编单个参数或路径段用 encodeURIComponent。九成场景你需要的是后者。
查询参数拼接的三个常见坑
我自己踩过最深的一次,是把一段 JSON 直接塞进查询参数没编码,接口稳定返回 400,盯着那串字符看了二十分钟才反应过来里面的 = 和 & 把整个查询串搅乱了。后来养成习惯:任何要进 URL 的值,先过一遍 encodeURIComponent。下面三个坑最值得提前知道。
第一,别用 Component 模式编整条 URL。它会把 :// 和 / 也转掉,https://a.com 变成 https%3A%2F%2Fa.com,直接点不开。整条链接用完整 URL 模式,Component 只留给单个参数。
第二,查询串里的字面 + 也得转义。在 form-urlencoded 约定里 + 代表空格,所以 ?eq=1+1=2 会被服务端读成「1 1=2」。要保住那个加号,得编成 1%2B1%3D2。
第三,别对一个根本没编码过的值做解码,也别重复编码。如果输出里出现 %25(也就是 % 本身的编码),比如本该是 %20 的地方变成了 %2520,说明这个值被编了两遍。稳妥做法是只在拼最终 URL 前编码一次,绝不对已经带 %xx 的值再编一次。
它和 HTML 实体编码不是一回事
经常有人把 URL 编码和 HTML 实体编码搞混。两者目标完全不同:URL 编码是为了让数据安全地待在地址栏里,用的是 %xx;HTML 实体编码是为了让 < > & 这些字符安全地待在网页正文里,用的是 < & 这种写法。一段文本如果既要进 URL 又要进 HTML,可能两道都得过。需要处理后者时,可以用 HTML 实体编码工具。
搞清楚谁负责哪一层,你拼出来的链接才不会一会儿乱码、一会儿被截断。URL 编码本身规则不复杂,难的是记住边界:整条链接还是单个零件,要不要保留结构字符,有没有重复编码。把这三件事想清楚,那串 %xx 就从噩梦变成了可读的工具。
Made by Toolora · Updated 2026-06-13