Vue项目中引入ESLint校验代码避免代码错误

目录
  • 1 ESLint 是什么
  • 2 在 Vue 项目中引入 ESLint
    • 2.1 引入 ESLint
    • 2.2 ESLint 配置
    • 2.3 执行 ESLint 代码检查
    • 2.4 自动修复 ESLint 问题
  • 3 配置 husky 和 PR 门禁
    • 3.1 配置 husky 门禁
    • 3.2 配置 PR 门禁
  • 4 常见的 ESLint 问题及修复案例
    • 4.1 案例1:
    • 4.2 案例2:
    • 4.3 案例3:
    • 4.4 案例4:
  • 5 感谢

1 ESLint 是什么

ESLint 是一个插件式的 JavaScript / JSX 代码检查工具,用于检测和修复 JavaScript 代码中的问题,目标是让代码更一致并避免错误。

2 在 Vue 项目中引入 ESLint

使用 Vue CLI 搭建的 Vue2 项目已经自带 ESLint,就不赘述,我们看下 Vite 搭建的 Vue3 项目中怎么引入 ESLint。

使用以下命令搭建一个 Vue3 项目:

npm create vite@latest vue3-project

创建之后,启动起来:

npm i
npm run dev

效果如下:

2.1 引入 ESLint

执行以下命令:

npm init @eslint/config

进入交互式界面,可通过上下方向键选择,通过按回车键确定。

第一个问题是:

  • 你希望用 ESLint 来干嘛?
  • 我们选择最全面的那个:检查语法,发现问题,并强制统一代码样式
$ npm init @eslint/config
? How would you like to use ESLint? …
  To check syntax only
  To check syntax and find problems
❯ To check syntax, find problems, and enforce code style

第二个问题是:

  • 你的项目用的是什么模块系统?
  • 因为是运行在浏览器端,选择 ESModule
? What type of modules does your project use? …
❯ JavaScript modules (import/export)
  CommonJS (require/exports)
  None of these

第三个问题是:

  • 你用的什么框架?(居然没有 Angular)
  • 选择 Vue
? Which framework does your project use? …
  React
❯ Vue.js
  None of these

第四个问题是:

  • 你是否使用 TypeScript?
  • 选择 Yes
? Does your project use TypeScript? › No / Yes

第五个问题是:

  • 你的代码运行在什么环境?(这个可以多选)
  • 选择 Browser 浏览器环境
? Where does your code run? …  (Press <space> to select, <a> to toggle all, <i> to invert selection)
 Browser
 Node

第六个问题是:

  • 你想定义怎样的代码风格?
  • 选择使用一个流行的代码风格
? How would you like to define a style for your project? …
❯ Use a popular style guide
  Answer questions about your style

第七个问题是:

  • 你想使用哪个样式风格?
  • Airbnb 用的人比较多,就选这个吧
? Which style guide do you want to follow? …
❯ Airbnb: https://github.com/airbnb/javascript
  Standard: https://github.com/standard/standard
  Google: https://github.com/google/eslint-config-google
  XO: https://github.com/xojs/eslint-config-xo

第八个问题是:

  • 配置文件用什么格式?
  • 就选 JavaScript 吧(生成 eslintrc.js 文件)
? What format do you want your config file to be in? …
❯ JavaScript
  YAML
  JSON

完成!是不是超级简单!

看下我们都选了哪些配置:

 How would you like to use ESLint? · style
 What type of modules does your project use? · esm
 Which framework does your project use? · vue
 Does your project use TypeScript? · Yes
 Where does your code run? · browser
 How would you like to define a style for your project? · guide
 Which style guide do you want to follow? · airbnb
 What format do you want your config file to be in? · JavaScript

主要给我们安装了以下依赖:

eslint-config-airbnb-base@15.0.0

eslint-plugin-import@2.26.0

eslint-plugin-vue@9.2.0

eslint@8.20.0

@typescript-eslint/parser@5.30.6

@typescript-eslint/eslint-plugin@5.30.6

并生成了一个 eslintrc.cjs 配置文件:

module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    'plugin:vue/vue3-essential',
    'airbnb-base',
  ],
  parserOptions: {
    ecmaVersion: 'latest',
    parser: '@typescript-eslint/parser',
    sourceType: 'module',
  },
  plugins: [
    'vue',
    '@typescript-eslint',
  ],
  // 自定义 rules 规则
  rules: {
  },
};

2.2 ESLint 配置

  • parser 解析器
  • extends 配置扩展
  • plugins 插件
  • rules 自定义规则 eslint.org/docs/latest…
  • eslint-disable-next-line 禁用ESLint

2.3 执行 ESLint 代码检查

在 package.json 文件的 scripts 中配置 lint 脚本命令:

"scripts": {
  "dev": "vite",
  "build": "vue-tsc --noEmit && vite build",
  "preview": "vite preview",
  // 配置 lint 脚本命令
  "lint": "eslint --ext .vue,.ts src/"
},

执行 lint 脚本命令:

npm run lint

出现了一堆报错:

/vue3-project/src/App.vue
  4:53  error  Missing semicolon  semi
/vue3-project/src/components/HelloWorld.vue
  2:26  error  Missing semicolon  semi
  4:31  error  Missing semicolon  semi
  6:21  error  Missing semicolon  semi
/vue3-project/src/main.ts
  1:32  error  Missing semicolon  semi
  2:21  error  Missing semicolon  semi
  3:28  error  Missing semicolon  semi
  5:29  error  Missing semicolon  semi
/vue3-project/src/vite-env.d.ts
  4:3   error  Expected 1 empty line after import statement not followed by another import  import/newline-after-import
  4:45  error  Missing semicolon                                                            semi
  5:48  error  Missing semicolon                                                            semi
  6:27  error  Missing semicolon                                                            semi
 12 problems (12 errors, 0 warnings)
  12 errors and 0 warnings potentially fixable with the `--fix` option.

大部分都是说句尾没有分号,因为我们选择的是 Airbnb 代码规范,所以会有这个报错提示,不同的代码规范,内置的检查规则不一定完全相同。

2.4 自动修复 ESLint 问题

在 scripts 中增加自动修复 ESLint 问题的脚本命令:

"scripts": {
  "dev": "vite",
  "build": "vue-tsc --noEmit && vite build",
  "preview": "vite preview",
  "lint": "eslint --ext .vue,.ts src/",
  // 自动修复 ESLint 问题脚本命令
  "lint:fix": "eslint --ext .vue,.ts src/ --fix"
},

执行:

npm run lint:fix

执行自动修复的命令之后,所有分号都加上了,未使用的变量也自动移除了。

再次执行:

npm run lint

没有再报错。

3 配置 husky 和 PR 门禁

3.1 配置 husky 门禁

为了确保每次提交(git commit)之前代码都通过 ESLint 检查,我们增加一个 pre-commit 门禁。

  • 第一步:安装 husky 和 lint-staged
npm i lint-staged husky -D
  • 第二步:在 package.json 的 scripts 中增加 prepare 脚本命令
"scripts": {
  "dev": "vite",
  "build": "vue-tsc --noEmit && vite build",
  "preview": "vite preview",
  "lint": "eslint --ext .vue,.ts src/",
  "lint:fix": "eslint --ext .vue,.ts src/ --fix",
  // 在 npm install 之后自动执行,生成`.husky`目录。
  "prepare": "husky install"
},
  • 第三步:执行 prepare 脚本
npm run prepare

该命令执行完会在项目根目录自动生成.husky目录。

  • 第四步:增加 pre-commit 钩子

执行以下命令,会在.husky目录自动生成pre-commit文件钩子。

npx husky add .husky/pre-commit "npx lint-staged"
  • 第五步:增加 lint-staged 配置
"lint-staged": {
  "src/**/*.{vue,ts}": "eslint --fix"
},

通过以上五个步骤,以后每次使用git commit命令提交提交代码,都会:

  • 被 pre-commit 钩子拦截
  • 执行 npx lint-staged 命令
  • 进而执行 eslint --fix 命令,对本次提交修改的代码涉及的文件进行代码检查,并自动修复能修复的错误,不能修复的错误会提示出来,只有所有 ESLint 错误都修复了才能提交成功

3.2 配置 PR 门禁

如果你在做自己的开源项目,并且非常幸运,有一群志同道合的小伙伴愿意一起参与贡献,这时为了统一大家的代码风格,让贡献者们专注于特性开发,不用担心代码格式规范问题,并通过 ESLint 工具提示贡献者,哪些代码可能带来潜在的风险,你就有必要给提交的 PR 加上 ESLint 门禁。

我们已经增加了本地的 ESLint 命令:

"scripts": {
  "lint": "eslint --ext .vue,.ts src/",
},

我们需要在本目录创建一个.github/workflows/pull-request.yml文件,在该文件中写入以下内容:

name: Pull Request
on:
  push:
    branches: [ dev, main ]
  pull_request:
    branches: [ dev, main ]
jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [16.x]
    name: "ESLint"
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Install pnpm
        uses: npm/action-setup@v2
        with:
          version: 6
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v2
        with:
          node-version: ${{ matrix.node-version }}
      - name: Install deps
        run: npm i
      - name: ESLint
        run: npm run lint

这样只要 PR 是往 dev 或 main 分支合入的,都会跑一遍这个 Github Actions 工作流任务,ESLint 检查不通过的话,PR 的 checks 里面会提示,拦截该 PR 的合入。

PR 的提交者看到提示,也可以点到任务里面去看是哪里报错,修改掉这些 ESLint 问题,PR 就会变成绿色,项目的管理员就可以顺利合入 PR 到目标分支啦

4 常见的 ESLint 问题及修复案例

接下来跟大家分享 Vue DevUI 开源 Vue3 组件库 ESLint 问题修复过程中遇到的典型问题。

4.1 案例1:

warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any

该问题出现频率比较高,原因是有些类型写了any,需要明确的类型。

比如Pagination组件的单元测试文件pagination.spec.ts中:

const wrapper = mount({
    components: {
        DPagination
    },
    template: `&lt;d-pagination ... /&gt;`
}, globalOption);
const btns = wrapper.findAll('a.devui-pagination-link');
expect(btns.map((ele: any) =&gt; ele.text()).join()).toEqual('&lt;,1,...,4,5,6,...,16,&gt;');

其中的ele: any就属于这类问题。

解决办法是给ele加上明确的类型,看逻辑是<button>元素,由于是@vue/test-utils库的包裹元素,因此需要包一层DOMWrapper

import { DOMWrapper } from '@vue/test-utils';
expect(btns.map((ele:  DOMWrapper&lt;Element&gt;) =&gt; ele.text()).join()).toEqual('&lt;,1,...,4,5,6,...,16,&gt;');

4.2 案例2:

'xxx' was used before it was defined no-use-before-define

这也是一个比较常见的问题,在声明之前使用变量或方法,解决办法也很简单,只需要调整下代码的顺序即可,将变量或方法的声明放在调用的语句之前。

比如Pagination组件的pagination.tsx中:

    // 极简模式下,可选的下拉选择页码
    const litePageOptions = computed(() =>  liteSelectOptions(totalPages.value));
    // 当前页码
    const cursor = computed({
      get() {
        // 是否需要修正错误的pageIndex
        if (!props.showTruePageIndex && props.pageIndex > totalPages.value) {
          emit('update:pageIndex', totalPages.value || 1);
          return totalPages.value || 1;
        }
        return props.pageIndex || 1;
      },
      set(val: number) {
        emit('update:pageIndex', val);
      }
    });
    // 总页数
    const totalPages = computed(() => Math.ceil(props.total / props.pageSize));

其中的totalPages的声明在比较靠后的位置,但是却在声明之前在litePageOptionscursor变量中都使用了totalPages,所以提示 ESLint 问题。

解决的方法就是将totalPages的声明放在litePageOptionscursor之前。

    // 总页数
    const totalPages = computed(() =&gt; Math.ceil(props.total / props.pageSize));
    // 极简模式下,可选的下拉选择页码
    const litePageOptions = computed(() =&gt;  liteSelectOptions(totalPages.value));
    // 当前页码
    const cursor = computed({ ... });

4.3 案例3:

warning Missing return type on function @typescript-eslint/explicit-module-boundary-types

该问题是因为函数缺少返回类型,比如Fullscreen组件utils.ts文件的launchImmersiveFullScreen方法中:

export const launchImmersiveFullScreen = async (docElement: any) =&gt; {
  let fullscreenLaunch = null;
  if (docElement.requestFullscreen) {
    fullscreenLaunch = docElement.requestFullscreen();
  } else if (docElement.mozRequestFullScreen) {
    fullscreenLaunch = docElement.mozRequestFullScreen();
  } else if (docElement.webkitRequestFullScreen) {
    fullscreenLaunch = Promise.resolve(docElement.webkitRequestFullScreen());
  } else if (docElement.msRequestFullscreen) {
    fullscreenLaunch = Promise.resolve(docElement.msRequestFullscreen());
  }
  return await fullscreenLaunch.then(() =&gt; !!document.fullscreenElement);
};

先看下launchImmersiveFullScreen方法的参数问题,docElement用了any,也缺失了返回类型,docElement其实就是document对象,可以使用HTMLElement类型,但是launchImmersiveFullScreen这个方法是用来启动沉浸式全屏的,为了实现浏览器兼容,比如使用了docElement.mozRequestFullScreen兼容火狐,而这些方法在HTMLElement中是没有的,会报TS类型错误,所以需要做一些改造。

interface CompatibleHTMLElement extends HTMLElement {
  mozRequestFullScreen?: () =&gt; void;
  webkitRequestFullScreen?: () =&gt; void;
  msRequestFullscreen?: () =&gt; void;
}

这里定义了一个CompatibleHTMLElement的类型,继承了HTMLElement,并增加了一些自定义的方法。

export const launchImmersiveFullScreen = async (docElement: CompatibleHTMLElement) =&gt; {
  ...
}

再来看下launchImmersiveFullScreen方法的返回类型问题。

return await fullscreenLaunch.then(() =&gt; !!document.fullscreenElement);

该方法返回了一个Promise对象,它的类型是一个泛型,我们需要传入具体的类型:

export const launchImmersiveFullScreen = async (docElement: CompatibleHTMLElement): Promise&lt;boolean&gt; =&gt; {
  ...
  return await fullscreenLaunch.then(() =&gt; !!document.fullscreenElement);
};

4.4 案例4:

'xxx' is already declared in the upper scope @typescript-eslint/no-shadow

这个问题是由于嵌套的作用域中定义了相同的变量名,比如Tree组件的use-checked.ts文件中:

export default function useChecked(...) {
  const onNodeClick = (item: TreeItem) => {
    // 这里定义了 id 变量
    const { id } = item;
    ...
    filter 里面又定义了一个 id 参数
    const currentSelectedItem = flatData.filter(({ id }) => currentSelected[id] && currentSelected[id] !== 'none');
    ...
  }
}

修改方式就是将其中一个 id 的名字改了,比如把里面的 id 改成 itemId:

const currentSelectedItem = flatData.filter(({ id: itemId }) => currentSelected[itemId] && currentSelected[itemId] !== 'none');

欢迎在评论区分享你在项目中遇到的 ESLint 问题

5 感谢

Vue DevUI 组件库 ESLint 问题清零之路上,不得不提的一位小伙伴就是 @linxiang07 同学,他从2022年3月到7月,持续4个多月,累计修复40多个组件的100多个 ESLint 问题,直到7月5日 ESLint 清零,并给 PR 添加 ESLint 门禁,后续 PR 如果未通过 ESLint 检查将无法合入。

感谢 linxiang 同学的付出!

以下是 linxiang 同学提交的部分PR:

linxiang 同学也因此成为 Vue DevUI 组件库 TOP3 的贡献者,并成为我们的 Committer 和管理员

值得一提的是 linxiang 同学还是我们的 VirtualList 虚拟列表组件和 Tree 组件等多个组件的田主和贡献者,并且完善了多个组件的单元测试,能力很强,是非常活跃和积极的贡献者。

以上就是Vue项目中引入ESLint校验代码避免代码错误的详细内容,更多关于Vue引入ESLint代码校验的资料请关注我们其它相关文章!

(0)

相关推荐

  • vue-cli创建项目时由esLint校验导致报错或警告的问题及解决

    目录 vue-cli创建项目时由esLint校验导致报错或警告 eslint语法限制项目报错解决 vue-cli创建项目时由esLint校验导致报错或警告 vue-cli创建项目后编写代码控制台一片黄 但不影响代码执行 但是看着就是很不爽啊 到网上搜索了一下这个问题,想起来初始化项目时安装了esLint校验工具 嗯,我看到了很多办法都是下面这样的 1.因为你设置了eslint,如果你不想有规范的js代码,可以重新初始化关掉eslint. Use ESLint to lint your code?

  • vue关于eslint空格缩进等的报错问题及解决

    目录 关于eslint空格缩进等的报错问题 解决办法有四种 eslint使用规则和各种报错对应规则 ESLint 主要有以下特点 关于eslint空格缩进等的报错问题 解决办法有四种 1. 在.eslintrc.js文件中添加如下代码: rules: { 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 'no-debugger': process.env.NODE_ENV === 'production'

  • vite项目添加eslint prettier及husky方法实例

    目录 1. 初始化vite项目 2. 添加eslint 3. 添加 prettier 4. 添加 husky和lint-staged 5. 配置commitlint 1. 初始化vite项目 npm init vite Project name: - vite-project // 项目名称,默认 vite-project Select a framework: › react // 选择框架 Select a variant: › react-ts // 选择组合 2. 添加eslint 安装

  • vue去掉严格开发,去掉vue-cli安装时的eslint或修改配置方式

    目录 直接上问题 问题原因 解决办法 vue-cli关闭eslint及配置eslint 关闭eslint的方法 配置eslint的方法 vuex自动修复的方法 直接上问题 当我运行vue项目时候:npm run dev 出现以下问题警告报错.(如下图) 问题原因 用vue-cli构建项目时安装了eslint选择了Y,这东西很蛋疼.tab键不能使用,必须换成两个空格.sublime可以选择tab键自动转换成空格键.要不你就不要安装eslint. 解决办法 只需要删掉 build/webpack.b

  • vue-cli构建的项目如何手动添加eslint配置

    目录 package.json里配置添加 根目录下添加检测配置js文件.eslintrc.js 添加忽略检测配置文件.eslintignore webpack.base.conf.js rules里添加eslint-loader配置 config->index.js的dev里添加 Eslint的一些规则说明 1.使用Eslint的时候如果出现未闭合标签会报红 2.需要在单行元素的内容之前和之后换行 package.json里配置添加 1.scripts里添加快捷eslint检查命令 "li

  • Vue项目中引入ESLint校验代码避免代码错误

    目录 1 ESLint 是什么 2 在 Vue 项目中引入 ESLint 2.1 引入 ESLint 2.2 ESLint 配置 2.3 执行 ESLint 代码检查 2.4 自动修复 ESLint 问题 3 配置 husky 和 PR 门禁 3.1 配置 husky 门禁 3.2 配置 PR 门禁 4 常见的 ESLint 问题及修复案例 4.1 案例1: 4.2 案例2: 4.3 案例3: 4.4 案例4: 5 感谢 1 ESLint 是什么 ESLint 是一个插件式的 JavaScrip

  • 在 Vue 项目中引入 tinymce 富文本编辑器的完整代码

    项目中原本使用的富文本编辑器是 wangEditor,这是一个很轻量.简洁编辑器 但是公司的业务升级,想要一个功能更全面的编辑器,我找了好久,目前常见的编辑器有这些: UEditor:百度前端的开源项目,功能强大,基于 jQuery,但已经没有再维护,而且限定了后端代码,修改起来比较费劲 bootstrap-wysiwyg:微型,易用,小而美,只是 Bootstrap + jQuery... kindEditor:功能强大,代码简洁,需要配置后台,而且好久没见更新了 wangEditor:轻量.

  • 在Vue项目中引入腾讯验证码服务的教程

    什么是腾讯验证码?它长这个样子--:point_down: 最近公司项目要求引入腾讯云验证,要求是这样的: 为了防止别人恶意刷短信验证码,当用户短时间内多次获取验证码的时候,需要调用腾讯验证码,验证成功后会继续自动发送验证码 ,刚开始的我听的一脸蒙蔽,网上搜索也没有多少相关的文章,然而现在我接通啦,发现是很简单点事(或许就是因为太简单了所以没有人写2333-) 不多BB,开始吧! 先看文档的接口调用流程: (文档地址: cloud.tencent.com/document/pr- ) 总共分成几

  • Vue项目vscode 安装eslint插件的方法(代码自动修复)

    ESlint:是用来统一JavaScript代码风格的工具,不包含css.html等. 方法和步骤: 通常情况下vue项目都会添加eslint组件,我们可以查看webpack的配置文件package.json查看,也可以查看工程下是否有.eslintrc.js和.eslintignore查看到eslint是否开启. 当我们编写不符合eslint规范的代码时,启动项目会报错,比如 这个时候可以安装vscode eslint插件,就可以自动检测不符合规范的代码.打开vscode左侧扩展面板,搜索es

  • vue项目中引入noVNC远程桌面的方法

    1 .首先,先简单介绍一下概念. VNCServer 是一个为了满足分布式用户共享服务器资源,而在服务器开启的一项服务,对应的客户端软件有图形化客户端 VNCViewer,而 noVNC 则是 HTML5 VNC 客户端,它采用 HTML 5 WebSocket, Canvas 和 JavaScript 实现. noVNC 被普遍用在各大云计算.虚拟机控制面板中.noVNC 采用 WebSockets 实现,但是当前大多 VNC 服务器不支持 WebSocket,所以 noVNC 不能直连 VN

  • 在vue项目中引入高德地图及其UI组件的方法

    引入高德地图: 打开index.html,引用高德地图的JavaScript API: <script type="text/javascript" src="http://webapi.amap.com/maps?v=1.3&key=你的API key"></script> 在"key="这里添加你申请的key,key不需要加引号. 引入高德地图UI组件,只需要在上面代码后面再加一串代码: <script

  • 在vue项目中引入vue-beauty操作方法

    vue-beauty有丰富的vue组件库,使用vue-beauty方便项目的开发,下面介绍在vue项目中引入vue-beauty. 1.vue项目初始化 npm install --global vue-cl:全局安装vue脚手架vue init webpack my-projec:初始化cd my-project:进入目录npm install:安装依赖 2.安装vue-beauty 3.查看配置文件package.json,是否有vue-beauty组件的版本号 4.在main.js中引入

  • Vue项目中引入 ECharts

    目录 1.安装 2.引入 3.使用 4.按需引入 ECharts 图表和组件 1.安装 使用如下命令通过 npm 安装 ECharts npm install echarts --save 2.引入 安装完成以后,可以将echarts全部引入,这样一来,我们可以在该页面使用echarts所有组件:引入代码如下: import * as echarts from "echarts"; 3.使用 引入完毕之后,我们可通过echarts提供的接口画出对应的图表,使用方法如下: <tem

  • 在vue项目中引入highcharts图表的方法(详解)

    npm进行highchars的导入,导入完成后就可以进行highchars的可视化组件开发了 npm install highcharts --save 1.components目录下新建一个chart.vue组件 <template> <div class="x-bar"> <div :id="id" :option="option"></div> </div> </templa

  • 在Vue项目中使用d3.js的实例代码

    之前写一个 Demo里面 有些东西要使用d3实现一些效果 但是在很多论坛找资源都找不到可以在Vue里面使用D3.js的方法,npm 上面的D3相对来说 可以说是很不人性化了 完全没有说 在webpack上怎么使用D3.js 最后折腾很久 看到某位外国大佬 看他的案例 成功的实现了在Vue项目里面实现D3的使用 首先安装 npm install d3 --save-dev 以防万一,然后看package.json 安装完成 在我们开始之前,让我们渲染一个Vue组件,它使用常规的D3 DOM操作呈现

随机推荐