奇怪的知识又又又增加了 大多數知識,文檔都能學到。遇到困惑,先看文檔。 文档怎么看? 有好多的是过时的,即使是官网的。 就像 rollup + ts + babel npm上找到对应的插件,然后看插件文档,babel的话直接去官网看
内存泄露
内存回收机制有 标记清楚,引用计数(由于存在循环引用等,现在不用这个方法了
项目崩溃,发现项目里内存泄露了 —
- settimeout,setInterval (蚊子腿 记得清除
- 闭包 (目前来说ES6语法很少涉及到
- 脱离DOM的引用(vue等类似框架,很少直接操作dom
- 全局变量!
- createObjectURL生成的地址->资源的映射 也会造成内存泄漏(及时用 revokeObjectURL清除
- createElement,cleateDocumentFragment,创建元素之后,未将变量置空
造成的原因就是全局变量,有个数组在被一直推入变量,永远不会调用清除方法
css
用rem布局,圆形或者圆环会变形
// 思路 先用两倍的宽高属性设置css样式,然后按照0.5倍缩放div {width: .4rem;height: .4rem;background-color: #C40000;border-radius: 50%;transform: scale(0.5);}
flex布局的时候文本溢出无效
// 对flex的元素增加最小宽度.flex {min-width: 0;}
JS
promise
全局变量覆盖
test = function () {let c = Math.random() * 10let promise = new Promise ((resolve, reject) => {window.doSomething = function (data) {setTimeout(() => {console.log('before resolve', data)resolve(data)}, c * 1000)}})return promise}// 情况1test().then(res => {console.log(res)})test().then(res => {console.log(res)})window.doSomething('12313')window.doSomething('hhhhh')// before resolve 12313// 12313// before resolve hhhhh// 情况2test().then(res => {console.log(res)})window.doSomething('12313')test().then(res => {console.log(res)})window.doSomething('hhhhh')// before resolve 12313// 12313// before resolve hhhhh// hhhhh
第二次调用 test 的时候, window.doSomething 被重写了,导致里面的 resolve 丢失,然后后面调用两次的时候,执行的都是后面一次赋值的方法。 这个时候使用下面的方法,就可以进行控制,以免window上的变量被覆盖。
Promise 执行列队,按照推入循序执行
class PromiseQueue {constructor () {this._queue = []// 当前队列有无promise在执行的标记this._flag = false}add (fn) {this._queue.push(fn)if (!this._flag) this.exce()}async exce () {this._flag = truewhile (this._queue.length > 0) {let tmp = this._queue.shift()try {await tmp()} catch (e) {console.log('err:', e)}}this._flag = false}}// usageconst q = new PromiseQueue()let callSdk = (params) => new Promise((rs, rj) => {let tmp = () => new Promise((resolve, reject) => {setTimeout((res) => {resolve()rs(params)}, Math.random() * 5000)})q.add(tmp)})callSdk(1).then(res => {console.log('res::', res)})callSdk(2).then(res => {console.log('res::', res)})callSdk(3).then(res => {console.log('res::', res)})可以用promise.race()判断是否有promise完成,不需要再嵌套一层promise
一个对象转换方法
var obj1 = {"user.name.firstname": "foo","user.age": 10}obj = {}Object.entries(obj1).forEach((item) => {let tempArr = item[0].split('.')tempArr.reduce((acc, cur, index) => {if(index === tempArr.length - 1) return acc[cur] = item[1]return acc[cur] = acc[cur] ? acc[cur] : {}}, obj)})console.log(obj)// 结果{user: {name: {firstname: 'foo'},age: 10}}
BigInt
**BigInt**是一种内置对象,它提供了一种方法来表示大于253 - 1的整数。这原本是 Javascript中可以用[Number](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number)表示的最大数字。**BigInt**可以表示任意大的整数 — mdn
遇到一个接口,返回值为
// 后端实际返回(在postman 和 浏览器直接输入地址let res = {key: 1212124121545233223}// 前端接收到的 (包括在控制台network看到的{key: 1212124121545233200}// 开始以为接口出错了,后面在控制台测试发现let c = 1212124121545233223c// 1212124121545233200// 原来是 bigint,js对大于2^53的整数显示和处理有限制// 然后就在请求中加入const JSONbig = require('json-bigint')axios({url: '***',transformResponse: function (data) { return JSONbig.parse(data) },params})// 使用的时候直接res.key.toString()
浏览器相关
忽略证书报错,加载service worker
// 生成证书,文件夹目录里运行,注意:common name 要设置为 localhostopenssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem// http-server 启动https 本地服务http-server -S -C cert.pem// 进入chrome 应用的文件夹,空格要用反斜杠转译cd /Applications/Google\ Chrome.app/Contents/MacOS// 启动忽略证书模式./Google\ Chrome --user-data-dir=/Users/buer/play/pwa --ignore-certificate-errors --unsafely-treat-insecure-origin-as-secure=https://localhost
vue自带 prefetch
vue-cli 路由懒加载,cli默认 prefetch 了其他懒加载路由。
请求相关
Referrer Policy
最新版 chrome 为了保证用户访问安全,出了一个新的功能
当你的 General 中没有设置 Referrer Policy 的时候,系统会默认设置为 strict-origin-when-cross-origin
也就是说,在请求头中,Referer 会只有域名,如下,导致 JsonP 类型的请求,后端不作处理返回 403
Referrer Policy: strict-origin-when-cross-originReferer: https://ts.hundsun.com/当设置 Referrer Policy 为 no-referrer-when-downgrade 的时候, 即Referrer Policy: no-referrer-when-downgrade此时,Referrer 字段会显示为全部,如下Referer: https://ts.hundsun.com/se/portal/SupportPortal.htm
Content-Type(常用的)
form-data 类型的请求体
**application/x-www-form-urlencoded** 此类型不适合传输大型的二进制数据**multipart/form-data** 此类型用于传输文件
json 类型的请求体
**application/json** 此类型适合后端要求接受 json
使用
data = {name: 'buer',age: 25}// application/x-www-form-urlencodedconfig.data = Qs.stringify(data)// application/jsonconfig.data = JSON.stringify(data)// multipart/form-dataconfig.data = data
封装axios
token一般会有一个过期时间,然后后端也会给一个过期时间,但是判断是否过期用的是系统时间,如果系统时间被修改,则造成token实际过期,依然发送请求,造成请求失败 不过刷新token这种最好方案还是后端解决!!!
思路
在axios 响应中判断是否无权限
- 无权限 - 请求token 再重新发送请求
- 有权限 - 正常进行
若同时有多个请求则用一个数组保存请求,等待获取到token后,再一并发送
响应拦截器修改
let isRefreshing = false // 是否在刷新的flaglet requests = [] // 保存请求数组instance.interceptors.response.use(response => {return response}, error => {if (!error.response) return Promise.reject(error)// 判断是否是无权限需要刷新tokenif (error.response.status === 401) {const { config } = error// 如果这是第一个请求 isRefreshing 为falseif (!isRefreshing) {isRefreshing = truereturn getToken().then(res => {const { token } = res.data// 存入缓存setToken(token)config.headers.Authorization = `Bearer ${access_token}`// 执行数组里所有保存起来的请求requests.forEach((cb) => cb(token))requests = []// 第一个请求通过这个地方返回return instance(config)})} else {// 未获取到token的时候return new Promise(resolve => {// 除第一个之外的请求保存在数组中request.push(token => {config.headers.Authorization = `Bearer ${access_token}`resolve(instance(config))})})}}return Promise.reject()})
git相关
HTTP2报错
Fix error : RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR
解决方案
设置git使用 http/1.1
git config --global http.version HTTP/1.1
工具
- 内网穿透 - ngrok
VS Code
格式化两次问题
一般vscode中的格式化顺序为 prettier > default > eslint
意味着 通常情况下 prettier 最后执行完毕。代码样式就由prettier决定了(所以其他程序格式化好后,再prettier格式化可能会闪烁)。同样的,如果同时开启 defalut和 eslint ,eslint格式化之后,也会闪烁一下,保存为最终的vscode默认格式化代码样式。
// 保存时使用VSCode 自身格式化程序格式化"editor.formatOnSave": true,// 保存时用eslint格式化"editor.codeActionsOnSave": {"source.fixAll.eslint": true}// 解决:// 1. 两者会在格式化js时冲突,所以需要关闭默认js格式化程序,即添加下面的"javascript.format.enable": false// 2. 或者是关闭掉vscode默认的格式化工具"editor.formatOnSave": false
npm包发布相关
npm login
Conflict - PUT https://registry.npm.taobao.org/-/user/org.couchdb.user:buera - [conflict] User buera already exists
设置正确的镜像源即可
npm config set registry https://registry.npmjs.org/
包依赖类型
dependencies
devDependencies
peerDenpendencies
如果有一些依赖包即使安装失败,项目仍然能够运行或者希望npm继续运行,就可以使用optionalDependencies。另外optionalDependencies会覆盖dependencies中的同名依赖包,所以不要在两个地方都写。
bundledDependencies
在发布的时候,希望一些依赖也出现在最终包里的话,可以将包名写在里面
{"name": "@buera/native-bridge-securities","bundledDependencies": ["@buera/native-bridge-core"]}
这样在安装 @buera/native-bridge-securities 这个包的时候,发现 @buera/native-bridge-core 这个包也会一起被安装
package.json 字段
module
pkg.main字段指向的应该是编译后生成的 ES5 版本的代码,而 module 字段会指向一个基于ES6模块规范的文件 这样在使用包的时候可以享受 TreeShaking 带来的好处,而ES5的好处是用户在大包的时候可以放心屏蔽掉 node_modules 目录
使用的时候,如果我们使用
// 使用 esmodule 模块,默认引用 module 字段指向的文件import { cc } from '@buera/native-bridge-securities'// 使用 AMD规范,RequireJS,默认饮用 main 字段指向的文件let cc = require('@buera/native-bridge-securities')
