# 开发问题记录

# 内存泄露

window.open 会导致内存泄露, 需要在第三个参数增加noopener

window.open(url, '_blank', 'noopener')

# Vscode 配置项

Vscode中配置fixAll选项会导致Eslint每次保存的时候出现卡顿,并提示正在保存 xxx, 正在从 Eslint 获取代码

"editor.codeActionsOnSave": {
 "source.fixAll.eslint": false, //此处需要将该值设为false
},

在本地开发中, 如果需要将服务的Cookie设置一个默认值, 那么可以采用以下两种方法中的任意一种

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        // 第一种方法
        onProxyReq(proxyReq) {
          proxyReq.setHeader(
            'Cookie',
            'Authorization=Bearer+gold-scalefb23a7ab783442859a3c8b438e50521b;'
          )
        },
        // 第二种方法
        headers: {
          Cookie: 'myToken=jx42NAQSFRwXJjyQLoax_sw7h1SdYGXog-gZL9bjFU7'
        }
      }
    }
  }
}

# SSL 证书问题

当 https 页面提示“您的连接不是私密连接”, 有如下解决方案

# 方案一 使用彩蛋

在 chrome 该页面上,直接键盘敲入这 12 个字符:`thisisunsafe`

注意:鼠标点击当前页面任意位置,让页面处于最上层即可输入

# 方案二 修改 hsts 配置

在chrome的地址栏里输入 chrome://net-internals/#hsts,把对应的域名从HSTS中删除,如下图:

# 方案三 修改无效证书配置

Chrome地址栏输入:chrome://flags/#allow-insecure-localhost

允许无效证书选项:

# 方案四 修改 Chrome 启动参数

# windows 系统

1.  找到你的 Chrome 快捷方式.
2.  右键图标,选择属性
3.  找到”目标”文本框,里面的内容是你的 Chrome 程序路径,类似这样 C:\\Users\\Administrator\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe
4.  在这段文本的后面输入一个空格,然后输入-ignore-certificate-errors
5.  修改后的文本应该类似于这样:C:\\Users\\Administrator\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe -ignore-certificate-errors
6.  点击确定
7.  重新打开你的 Chrome 浏览器

# mac 系统

# 打开 /etc/chromium.d/default-flags 编辑,添加一行:
# 其中 --ignore-certificate-errors 是重点,跳过不信任 Error。不加 --test-type 打开浏览器会有警告,加上之后就没事儿了。
# Disable HTTPS Error Report
export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --ignore-certificate-errors --test-type"

# 方案六 命令行启动

该方式适合类 unix 系统

open -n /Applications/Google\ Chrome.app/ --args  --ignore-certificate-errors --ignore-urlfetcher-cert-requests --user-data-dir=/Users/lorain/MyChromeDevUserData/

# Maas 代码风格检查配置

maas 项目众多, 问题比较类似, 不支持可选链?., 也不支持空值合并 ??, 本章节记录解决过程

# 安装依赖

  • "eslint": "^7.32.0"
  • "eslint-plugin-vue": "^8.2.0"
  • "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0"
  • "@babel/plugin-proposal-optional-chaining": "^7.16.0"

# 修改.eslintrc

修改之前的 eslint 配置, 加入以下内容即可

module.exports = {
  env: {
    es2020: true
  },
  parser: 'vue-eslint-parser',
  parserOptions: {
    ecmaVersion: 12,
    parser: 'babel-eslint'
  }
}

# 修改 babel.config.js

在原有的配置上新增下列两行

module.exports = {
  plugins: [
    '@babel/plugin-proposal-optional-chaining',
    '@babel/plugin-proposal-nullish-coalescing-operator'
  ]
}

# 扩展 prettier

加入如下依赖:

  • "prettier": "^2.2.1"
  • "eslint-plugin-prettier": "^3.3.1"
  • "@vue/eslint-config-prettier": "^6.0.0"

修改 eslintrc.js

module.exports = {
  extends: ['plugin:vue/essential', '@vue/standard', '@vue/prettier']
}

加入 prettier.config.js

module.exports = {
  semi: false,
  singleQuote: true,
  trailingComma: 'none',
  printWidth: 120
}

# 生产开启 vue-devtools

需要先获取 vue 根实例, 然后再设置方法重新开启 chrome devtools

// Vue 实例是挂载在元素的 `__vue__` 属性上的
app = document.querySelector('#app').__vue__

// 获取此实例的构造函数
Vue = app.constructor

// 获取 `Vue` 基类,只有基类上有 `Vue.config` 属性
while (Vue.super) {
  Vue = Vue.super
}

// 尝试打印 Vue.config
console.log(Vue.config)

Vue.config.devtools = true

__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue = Vue

# Iframe 通信

通过iframe嵌入其他页面, 如果两个系统跨域, 那么父窗口无法获取到iframe.contentDocument, 但是contentWindow都能获取到。

在多级页面嵌套中, 有三个关键变量selftopparent, 他们的区别如下:

  • self 总是指向当前窗口的 window
  • top 总是指向顶层窗口的 window
  • parent 如果存在多级前端, 是指当前窗口的父窗口

在预防CSRF攻击的处理中, 也能通过self === top来判断是否为顶层窗口

# PostMessage

iframe的通信中, 经常使用到postMessage, 该 api 的定义为:

otherWindow.postMessage(message, targetOrigin, [transfer])

该处的otherWindow是指收消息方窗口的引用:

<!--a.html-->
<iframe
  id="iframe"
  src="http://10.242.168.52:8082/code-segment/postMessage/b.html"
  style="display:none;"
></iframe>
<script>
  const iframe = document.getElementById('iframe')
  iframe.onload = function () {
    const data = { name: 'aym' }
    // 向domain2传送跨域数据
    iframe.contentWindow.postMessage(JSON.stringify(data), '*')
  }

  // 接受domain2返回数据
  window.addEventListener(
    'message',
    (e) => {
      console.log('data from b.html ---> ', e.data)
    },
    false
  )
</script>