vue3 解決 ESLint 各型別錯誤

Shyla發表於2022-07-16

前期專案中忽略了 eslint 檢查,導致一執行 npm run lint 出現兩千多條錯誤(இдஇ; ) 造孽啊
花了兩三天搞完,做個錯誤彙總。

環境和配置

專案用 vue@3.2 + vite + ant-design@6.0
關於eslint 配置的用法可參考:ESLint中文
eslint 有專門應用於 vue 的外掛:eslint-plugin-vue
大致貼一下版本依賴

devDependencies: {
    "@babel/eslint-parser": "^7.18.2",
    "eslint": "^8.7.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-import-resolver-alias": "^1.1.2",
    "eslint-plugin-import": "^2.25.4",
    "eslint-plugin-jest": "^25.7.0",
    "eslint-plugin-vue": "^8.3.0",
}

eslint 的配置採用 JS 檔案格式,經過幾次修改已經忘了一開始的內容,只貼基礎配置如下:

// .eslintrc.js
module.exports = {
    // 只作用於當前目錄
    root: true,
    // 執行環境
    env: {
        node: true,
        es6: true,
    },
    // 解析器
    parser: '@babel/eslint-parser',
    // 解析器選項
    parserOptions: {
        sourceType: 'module',
    },
    // 外掛
    plugins: ['import'],
    // 擴充套件配置
    extends: [
        'plugin:vue/vue3-recommended',
        'plugin:import/recommended',
        'prettier',
    ],
    // 啟用規則
    rules: {},
    // 全域性變數
    globals: {
        h: true,
    },
    // 為指定檔案指定處理器
    overrides: [
        {
            files: ['*.vue', '*.jsx'],
            parser: 'vue-eslint-parser',
            parserOptions: {
                ecmaVersion: 2018,
            },
            rules: {}
        }
    ],
}

ERROR: Parsing error: Unexpected token .

錯誤程式碼:

const isOpen = data?.form?.isOpen || false;

原來是無法識別可選鏈操作符(?.),但是擴充套件運算子沒問題,看了eslint 的配置,發現是 ECMAScript 的版本設定了2018(ES9),而可選鏈操作符是 ES2020(如果沒記錯),修改配置就可以了

// .eslintrc.js
module.exports = {
    parserOptions: {
        // ES版本,最新可設定 2022 or "latest",overrides 中配置了有需要也要同步修改
        ecmaVersion: 2020,
        sourceType: 'module',
    }
}

ERROR: Unable to resolve path to module

錯誤程式碼:

import Upload from '@/components/upload/index.vue'

路徑引用錯誤??看起來沒毛病,vite.config.js中明明配置了短鏈

resolve: {
    alias: {
        '@': pathResolve('src'),
    }
}

但 eslint 並不會自動讀取 vite 的配置,因此 eslint 也要加上對應配置:

// .eslintrc.js
module.exports = {
    settings: {
        'import/resolver': {
            alias: {
                map: ['@': './src']
            }
        }
    }
}

另外引入 vue 檔案需要加上字尾.vue,否則也會報相同錯誤。


ERROR: 'ref' is not defined

錯誤程式碼:

setup(){
    const isOpen = ref(false);
    return {
        isOpen,
    }
}

執行都沒報錯,怎麼突然 undefined 了??
等等,因為偷懶,vue 的語法糖都是unplugin-auto-import每個檔案自動引入的:

// vite.config.js
import autoImport from 'unplugin-auto-import/vite';

autoImport({
    imports: [
        'vue',
        'vue-router',
    ]
})

所以也要讓 eslint 知道,先生成一個包含所有變數的檔案:

// vite.config.js
autoImport({
    ...last,
    eslintrc: {
        // 已存在檔案設定預設 false,需要更新時再開啟,防止每次更新都重新生成
        enabled: false,
        // 生成檔案地址和名稱
        filepath: './.eslintrc-auto-import.json',
        globalsPropValue: true,
    }
})

上面的enabled在生成檔案後建議關閉,否則每次更新都會重新生成。
擴充套件到 eslint:

// .eslintrc.js
module.exports = {
    extends: [
        'plugin:vue/vue3-recommended',
        'plugin:import/recommended',
        'prettier',
        './.eslintrc-auto-import.json'
    ],
}

ERROR: vue/no-mutating-props

錯誤程式碼:

<!-- parent.vue -->
<template>
    <Child v-model:open="openModal" />
</template>
<script>
export default{
    setup(){
        const openModal = ref(false);
        return {
            openModal,
        }
    }
}
</script>

<!-- child.vue -->
<template>
    <a-modal v-model:visible="open"></a-modal>
</template>

<script>
export default{
    props: {
        open: {
            type: Boolean,
            default: true,
        }
    },
}
</script>

這是個低階錯誤,vue3支援多個引數雙向繫結,但是子元件不能直接修改props,需要轉換一下:

  • 方法一:用computed代替

    <template>
      <a-modal v-model:visible="isOpen"></a-modal>
    </template>
    
    <script>
    export default{
      props: {
          open: {
              type: Boolean,
              default: true,
          }
      },
      setup(props, { emit }){
          const isOpen = computed({
              get: () => {
                  return props.open;
              },
              set: (value) => {
                  emit('update:open', value);
              },
          });
    
          return {
              isOpen,
          }
      },
    }
    </script>
  • 方法二:用watch監聽

    <template>
      <a-modal v-model:visible="isOpen"></a-modal>
    </template>
    
    <script>
    export default{
      props: {
          open: {
              type: Boolean,
              default: true,
          }
      },
      setup(props, { emit }){
          const isOpen = ref(props.open);
          
          watch(
              () => isOpen.value,
              (value) => emit('update:open', value)
          );
    
          return {
              isOpen,
          }
      },
    }
    </script>

ERROR: no-console

錯誤程式碼:

console.log(data);

eslint 的規則設定了不能有console,當然可以改配置:

// .eslintrc.js
rules: {
    'no-console': 'off',
    // or:
    'no-console': [2, { allow: ['warn', 'error'] }],
    // or:
    'no-console': process.env.NODE_ENV === 'production' ? [2, { allow: ['warn', 'error'] }] : 'off'
}

提這個錯誤是為了引入下面的問題,在某些地方需要列印但不希望 eslint 報錯,可以讓其忽略檢查:

// 忽略整個檔案在第一行加
/* eslint-disable */

// 忽略一段程式碼檢查
/* eslint-disable */
...this our codes;
/* eslint-enable */

// 忽略一行程式碼檢查
console.log(data); // eslint-disable-line

// 忽略下一行程式碼檢查
// eslint-disable-next-line
console.log(data);

那麼在<template>中呢?

<template>
    <!-- eslint-disable -->
    <div v-for="item in options">{{ item }}</div>
</template>

然後發現不行,會報vue/require-v-for-key錯誤,註釋失敗。
找了各種文章最後發現是自己的鍋Ծ‸Ծ,找不出問題的時候還是要看官方文件,在eslint-plugin-vue已有說明vue/comment-directive規則就是用於忽略程式碼檢查,一看 eslint 的檔案配置果然是關閉了:

// .eslintrc.js
rules: {
    'vue/comment-directive': 'off',
}

改為error,完美؏؏☝ᖗ乛◡乛ᖘ☝؏؏


收工。

相關文章