五花八门的爬坑记录

1,076 阅读3分钟

健忘的秃头青年,记录一下平时遇到的跳坑&爬坑

求生环境: vue+electron

UI

在vue中引入jsoneditor

npm install jsoneditor --save
npm install

在main.js中

import jsoneditor from 'jsoneditor'
Vue.prototype.$jsoneditor = jsoneditor

以上是各网站给的导入方法,但是页面上会变成:

json-editor.PNG

所以一定要引入css文件

import 'jsoneditor/dist/jsoneditor.css'

但这时候可能svg不兼容,出现错误Error: No mime type for file with extension svgsupported,所以在webpack.base.conf.js中需要加入

{
  test: /\.svg$/,
  loader: 'file-loader',
}

vue-material

md-select使用时报错

[MdOption] Cannot read property 'trim' of undefined

当md-option内包含element而非字符串时,将报错 "TypeError: Cannot read property 'trim' of undefined"

在VUE文件中,当不得不在md-option中加element时,可以采用增加 的方法来work aroud。

当配合vue-form-json-schema时,则需要增加一个children在element之前:

mdSelectChildren.push({
  component: 'md-option',
  children: ['add an empty element to avoid trim() error', {
    component: 'span',
    fieldOptions: {
      domProps: { innerHTML: _value }
    }
  }],
  fieldOptions: {
    props: { value: _value }
  }
})

但是!这时候可能会导致,第一次获取ui schema的时候,value的值未绑定!

md-select-no-value.PNG

如上图,可以看到,当把值显示到label时,其实值是正确的(蓝圈内),但值并没有被正确绑定,所以该域显示为空。一旦再次获取ui schema,将绑定。

  • workaround:

在opened中,重复一次

process.nextTick(() => {
  this.updateUISchema()
})

JS

class中method之间互相调用

直接用this

class A{
    B(){
        this.C();
    }
    C(){
    }
}

将object转换为带换行的json

JSON.stringify()方法可以传三个参数。(value[, replacer[, space]])

JSON.stringify(obj, null, 2);

http

got+FormData

  • vue有自带FormData:

但是使用got发送时,必须使用npm的FormData: const FormData = require('form-data');

  • header 设置为formData.getHeaders()
let formHeaders = uploadData.getHeaders();
let options = {
    headers: {
       ...formHeaders,
    },
    body: uploadData
};

  • 增加上传的附件
uploadData.append('keyForJson', JSON.stringify(data));
uploadData.append('keyForFile', fs.createReadStream(filePath));

got 拦截已发送的request

let request = got(requestUrl, options);

request.then((res)=>{
  resolve(res);
 },(err) => {
  if (request.isCanceled){
    err = 'User canceled...'
  }
  reject(err)
});

在其他funtion中
request.cancel();

正则

判断字符串是否全英文

if (/[^ -~]+/.test(string)) {
  // Contains non-English letters
}

if (/[ -~]+/.test(string)) {
  // All English letters
}

分解文件名及后缀

fileName = "test.json".match(/(.*)\.[^.]+/)[1];
	fileName[0]: "test.json"
	fileName[1]: "test"

截取指定字符串中间的内容(数字)

let err = error.match(/(?<=statusCode *)\d+/);
	statusCode 502 bad gateway -> 502

截取<li></li>中间的内容

bulletsReg = /[^><]+(?=<\/li>)/g

获取<a>里面的href

linkReg = /(?<=href=" *).+?(?=")/g

配置

vue-electron with cli2

antd-vue

配置主题色

// webpack.config.js
module.exports = {
  rules: [{
    test: /\.less$/,
    use: [{
      loader: 'style-loader',
    }, {
      loader: 'css-loader', // translates CSS into CommonJS
    }, {
      loader: 'less-loader', // compiles Less to CSS
      options: { // using less-loader@5
         modifyVars: {
           'primary-color': '#1DA57A',
           'link-color': '#1DA57A'
         },
         javascriptEnabled: true,
       }
    }],
    // ...other rules
  }],
  // ...other config
}

不生效,需要将引入的antd样式改为Less格式

ant-design-vue/dist/antd.less

此时报错

Error evaluating function `unit`: the first argument to unit must be a number......

修改less的版本到3以下"less": "^2.7.3"

build

即使在管理员模式下,依然permission denied

报错:

Error: EPERM: operation not permitted, open 'C:\...\build\builder-effective-config.yaml'

在文件夹内找到该文件,修改Read-only unchecked!

打包好后无法运行

报错:

A JavaScript error occurred in the main process

确认package.json中

    "pack": "npm run pack:main && npm run pack:renderer",
    "pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js",
    "pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js",

所以正确的顺序是先运行npm run pack,生成main.js和render.js和index.html之后,再运行npm run build。

package.json中配置:

"main": "dist/electron/main.js"

pack失败卡住

报错:

92% chunk asset optimization BabelMinifyPlugin

反正app不打算外传,取消这个压缩plugin 在webpack.renderer.config.js里,注释掉

// const MinifyPlugin = require("babel-minify-webpack-plugin")

// new MinifyPlugin({
//   parallel: false
// }),

build开始时会清除dist下的main.js文件

报错:

Error: Application entry file "dist\electron\main.js" in the "C:\...\build\win-unpacked\resources\app.asar" does not exist. Seems like a wrong configuration.

修改build.js中的

del.sync(['dist/electron/*', '!.gitkeep'])

改为

del.sync(['!.gitkeep'])

unit test

vue + jest

circular reference error

Test suite failed to run
...
SyntaxError: Unexpected token '.'
...
      350 | import stringUtils from '../utils/stringUtils.js'

看起来就像没有配置babel一样,但实际上只是error message相同,root cause不同。 这里的root cause是因为在vuex的.js文件中,import了router,进行了route的修改。这是不正确的。 应该直接在.vue文件中使用this.$route

测试vuex的情况

import Vuex from 'vuex'
import { cloneDeep } from 'lodash'

const localVue = createLocalVue()
localVue.use(Vuex)

const store = new Vuex.Store({
    modules: {
        DBdata: {
            ...cloneDeep(DBdata), namespaced: true
        }
    }
})

wrapper = mount(VUEfile, { store, localVue })

测试带module的vuex

预设mock的store

getters = {
    titleLocal: () => 'title local',
}

报错:[vuex] unknown getter: schemaUI/titleLocal 应该使用:

'schemaUI/titleLocal': () => 'title local',

测试vue-router的变化情况

如果不需要测试变化,只需要取值,可以采用mock方法 如果需要测试变化,则需要引入router

import VueRouter from 'vue-router'

const localVue = createLocalVue()
localVue.use(VueRouter)
const router = new VueRouter()

wrapper = mount(VUEfile, { localVue, router })

测试页面初始route:

在beforeAll()中加入:

router.push({
  query: {
    product: 'switch'
  }
})

断言中途route情况:

expect(router.history.current.query.tab).toBe('components')

测试window.bus

main.js

...
window.bus = new Vue()
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

xx.test.js

beforeAll (() => {
  ...
  window.bus = new Vue()
  ...
  wrapper = shallowMount(products, { store, localVue, router })
}

eslint

创建自定义规则

因为项目中期才加入vuex的strict mode,所以出现了很多error。如在mutation以外的地方修改了state,且只有run time的时候才会检查出来。这导致在开发过程在经常被这个error闪退。

现在需要加入一个eslint规则,帮助筛查出所有mutation以外修改state的地方。

需要以下几个步骤:

  1. 创建自定义规则插件

    参考# Writing your own ESLint Plugins

    在Main的父目录,创建文件夹/customEslintRule

2024-01-16.png

2024-01-16_1.png 2. 编写自定义规则

借助AST,编写rule。

参考:# 如何编写一个自定义的 eslint 规则?

官网:规则结构

辅助工具:AST Explorer

我瞎写了一个,但这个只能静态检查在actions里头是否有修改state变量,可用场景非常局限。

create: function(context) {
  return {
      VariableDeclarator(node) {
        if (node.id.name === 'actions') {
          node.init.properties.forEach((fnNode) => {
            const findAssignmentExpression = function(node) {
              if (node.body && Array.isArray(node.body)) {
                node.body.forEach((bodyNode) => findAssignmentExpression(bodyNode))
              }
              if (node.type === 'ExpressionStatement') {
                const expressNode = node.expression
                if (expressNode && expressNode.left && 
                  expressNode.left.type === 'MemberExpression' &&
                  expressNode.left.object.name === 'state') {
                    context.report({
                      node: expressNode,
                      message: `Do not mutate Vuex store state outside mutation handlers.`,
                    });
                }
              }
            }
            return findAssignmentExpression(fnNode.value.body)
          });
        }
      }
  };
},

3. 链接本地插件

在/customEslintRule文件夹下,运行`sudo npm link`

在/Main文件夹下,运行`sudo npm link eslint-plugin-vuex-mutation`

4. 配置eslint文件

在.eslintrc.js文件里,加入:

    'plugins': [vuex-mutation]'  -> plugin ID
    'rules': {
        'vuex-mutation/vuex-mutation-id': 2   -> plugin ID / rule ID
    }

5. 运行 npm run lint