encodeURI 还是 encodeURIComponent?90% 的前端用错过
火力盒子技术专栏 · 本文提到的工具全部免费、在浏览器本地运行:https://www.ahotbox.com
前端最容易被误用的 API 排行榜,URL 编码这对兄弟一定上榜。它们长得很像、名字很像,但编码范围完全不同——用错一个,轻则参数丢失,重则接口 500。
一句话记住区别
encodeURIComponent:编码整个值。除了A-Z a-z 0-9 - _ . ! ~ * ' ( ),其他全部转义。拼参数用它。encodeURI:保留 URL 结构字符(/ ? : # & =),只编码非法字符。编码完整 URL 用它。
const q = 'a=1&b=中';
encodeURIComponent(q); // "a%3D1%26b%3D%E4%B8%AD" ✅ 作为参数值安全
encodeURI(q); // "a=1&b=%E4%B8%AD" ❌ & 和 = 没被转义
看到了吗?encodeURI 把 &、= 原样留下了。如果你把 q 拼到 ?query= 后面,服务端会把 a=1 和 b=中 当成两个参数——数据被静默拆散,而且不报错,是那种最难查的 Bug。
高频翻车现场
现场 1:encodeURI 编码参数
// ❌ 错误写法,& 被误当成参数分隔符
const url = encodeURI(`/search?q=${keyword}&page=1`);
// ✅ 正确写法:参数值单独编码
const url = `/search?q=${encodeURIComponent(keyword)}&page=1`;
现场 2:+ 号的歧义
空格有两种编码:encodeURIComponent(' ') 得到 %20,而老式的 application/x-www-form-urlencoded(HTML 表单、PHP)用 +。服务端如果按表单规则解码 %2B 和 + 都会变成空格——真正的加号传过去就丢了:
encodeURIComponent('1+1=2'); // "1%2B1%3D2" —— 加号被显式编码,安全
如果你发现传参里的 + 变成了空格,就是这个原因:上游用了表单式编码,或者服务端用了表单式解码。
现场 3:双重编码
先编码一次拼进 URL,中间件又编码一次,%20 变成 %2520。解码时就会出现"为什么我拿到的是 %20 而不是空格"。原则:编码只做一次,谁拼参数谁编码。
现场 4:中文没编码直接发
有的库(如 axios 的 params 参数)会自动编码,自己拼 URL 就得手动。中文直接放 URL 里,不同服务器的容忍度不同——Go 会拒绝,Nginx 可能 400。别赌,统一 encodeURIComponent。
速查表
| 场景 | 用什么 |
|---|---|
| query 参数值 | encodeURIComponent |
| path 中的动态段 | encodeURIComponent(再去掉多余的 /) |
| 完整 URL(含结构字符) | encodeURI |
| 解析参数值 | decodeURIComponent |
| 表单编码 | URLSearchParams(自动处理 + 和空格) |
实际开发最快的办法:用 URL 编解码工具 直接粘贴对比两种编码结果,或者用 URL 解析器 检查一个复杂 URL 的每个参数到底长什么样。
关于火力盒子:ahotbox.com 收录 1000+ 款免费纯前端工具(开发、文本、时间、转换、生成器等),所有数据在浏览器本地处理,无需注册、不上传数据、支持离线使用。
发布建议:公众号直接使用本文;掘金/CSDN 标题可改为《一次线上事故:encodeURIComponent 用错导致的参数丢失》;知乎适合回答"encodeURI 和 encodeURIComponent 的区别"类问题。
💡 关于火力盒子:ahotbox.com
收录 1000+ 款免费纯前端在线工具(开发、文本、时间、生成器、安全等),所有数据在浏览器本地处理,无需注册、不上传数据、支持离线使用。