[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
进行编码。我们可以通过encodeURIComponent
和 decodeURIComponent
这两个方法:
// 编码
window.btoa(encodeURIComponent('中文')) // "JUU0JUI4JUFEJUU2JTk2JTg3"
// 解码
decodeURIComponent(window.atob('JUU0JUI4JUFEJUU2JTk2JTg3')); // "中文"
1.3 GitHub API 获取 README 的中文乱码问题
通过encodeURIComponent
、decodeURIComponent
的方式解码 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()
5. JS新语法
5.1 js 双冒号运算符(::)
双冒号运算符::是 ES7 中提出的函数绑定运算符,用来取代call()、apply()、bind()调用。
双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。
foo::bar;
// 等同于
bar.bind(foo);
foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);
如果双冒号左边为空,右边是一个对象的方法,则等于将该方法绑定在该对象上面。
var method = obj::obj.foo;
// 等同于
var method = ::obj.foo;
let log = ::console.log;
// 等同于
var log = console.log.bind(console);
在react中应用
<div onChange={::this.handleChange}></div>
onChange={::this.handleChange} 等价于 onChange={this::this.handleChange} 即 onChange={this.handleChange.bind(this)}
转载自:https://blog.csdn.net/Misnice/article/details/137245923