[TOC]

JS常见问题解决

1. atob、base64加密中文乱码

前端在把数据进行 base64 编码加密时,一般是通过window.btoa()方法对数据编码,使用window.atob()进行解码。这种方法存在的问题。

1.1 报错原因

window.btoa() 不支持中文,仅支持 ASCII 编码。在浏Chrome览器终端对中文进行编码,会发现报错:

window.btoa('中文')

Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.
    at <anonymous>:1:8

window.atob()转换含有中文的 base64编码的时候中文部分会变为乱码。

在bash终端获取中文两个字的 base64 编码:

~ echo 中文 | base64
5Lit5paHCg==         # 解码:echo 5Lit5paHCg== | base64 -D

在浏Chrome览器终端通过window.atob()对其进行解码,可以发现是乱码:

window.atob('5Lit5paHCg==')
// "中文\n"

1.2 通过 encodeURIComponent 和 decodeURIComponent 转义中文字符

由于btoa 方法仅支持 ASCII 编码,所以我们可以先将中文转为ASCII字符,然后在使用btoa 进行编码。我们可以通过encodeURIComponentdecodeURIComponent 这两个方法:

// 编码 
window.btoa(encodeURIComponent('中文'))  // "JUU0JUI4JUFEJUU2JTk2JTg3"
// 解码
decodeURIComponent(window.atob('JUU0JUI4JUFEJUU2JTk2JTg3')); // "中文"

1.3 GitHub API 获取 README 的中文乱码问题

通过encodeURIComponentdecodeURIComponent 的方式解码 github 的 readme 数据的时候仍旧是乱码, 经过查找相关资料发现了Base64的编码与解码转的最优方案是下面这种:

function utf8_to_b64(str) {
    return window.btoa(unescape(encodeURIComponent(str)));
}
function b64_to_utf8(str) {
    return decodeURIComponent(escape(window.atob(str)));
}

// Usage:
utf8_to_b64('✓ à la mode'); // JTI1dTI3MTMlMjUyMCUyNUUwJTI1MjBsYSUyNTIwbW9kZQ==
b64_to_utf8('JTI1dTI3MTMlMjUyMCUyNUUwJTI1MjBsYSUyNTIwbW9kZQ=='); // "✓ à la mode"

utf8_to_b64('I \u2661 Unicode!'); // SSUyNTIwJTI1dTI2NjElMjUyMFVuaWNvZGUlMjUyMQ==
b64_to_utf8('SSUyNTIwJTI1dTI2NjElMjUyMFVuaWNvZGUlMjUyMQ=='); // "I ♡ Unicode!"

参考资料:https://blog.csdn.net/abxn2002/article/details/50887594

2. IE11浏览器文件下载乱码

页面中下载一个附件,在其他浏览器都是正常下载,在IE11浏览器里面则是打开了一个新标签页后,显示乱码,经过在网络上查找资料:

https://blog.csdn.net/itmyhome1990/article/details/103032316

浏览器通常使用MIME类型(而不是文件扩展名)来确定如何处理URL,因此Web服务器在响应头中添加正确的MIME类型非常重要。如果配置不正确,浏览器可能会曲解文件内容,网站将无法正常工作,并且下载的文件也会被错误处理。

因此需要后端设置正确的文件类型,IE浏览器才能正确处理下载的文件,以tomcat服务为例:

<mime-mapping>
	<extension>docx</extension>
	<mime-type>application/vnd.openxmlformats-officedocument.wordprocessingml.document</mime-type>
</mime-mapping>

问过后端同事:后端代码需要指定一个响应http头,将contentType设置为正确的文件类型。

3. 未编译的ES6语法在部分旧版本浏览器中不支持导致报错

在使用原生JS代码嵌入到html中执行时,部分ES6以上的语法会报错,比如:

  • ES2020新增的操作符?.??

上面的操作符在旧版本的浏览器中不支持导致JS报错

4. 页面中JS设置iframe的src不变,导致iframe不刷新内容

页面顶部是查询条件,下面是内嵌的iframe页面,点击查询按钮会把查询条件拼接到链接中然后更新iframe的src链接, 但是当查询条件没有修改的时候,链接没有改版,当更新iframe的src链接后,iframe页面的内容不会更新。

解决方法:链接中加一个无意义的参数,每次点击查询按钮的时候,都会改变这个参数,这样src 的链接每次都不一样,就会请求新的数据了,这个随时改变的参数一般是时间戳(到毫秒):

let time2 = new Date().getTime(); // 1646379926674,精确到毫秒
let time3 = new Date().valueOf(); // 1646379926674.精确到毫秒
let time4 = Date.now(); // 1646379926674,精确到毫秒,实际上是new Date().getTime()
Last Updated: 3/4/2022, 3:55:40 PM