跳到主要内容

Vue 规则

eslint-plugin-vue 是 Vue 官方推荐的规则集。它专注于 Vue 单文件组件(.vue文件)的特定规则,来确保Vue组件的正确性和最佳实践。

@vue/eslint-config-airbnb-with-typescript 是 Airbnb 风格指南的 Vue 和 TypeScript 版本。它将 Airbnb 久经考验的 JavaScript 和 TypeScript 最佳实践应用于 Vue 项目。

提示
// .eslintrc.js
require("@rushstack/eslint-patch/modern-module-resolution");

module.exports = {
extends: [
'plugin:vue/recommended',
'@vue/eslint-config-airbnb-with-typescript',
// '@vue/eslint-config-airbnb-with-typescript/allow-tsx-in-vue',
'plugin:vue-scoped-css/vue3-recommended',
],
};
注意
  • 由于上游依赖关系,@vue/eslint-config-airbnb-with-typescript 仍不支持 ESLint 9.x 版本,使用时请注意。使用时请使用 ESLint 8.x 版本,后续请及时关注版本变化。
  • 根据项目实际情况,决定是否开启 tsx 支持。

基础规则 JavaScript

规则名称错误级别配置选项描述
import/extensionserror["ignorePackages", { js: "never", mjs: "never", jsx: "never", vue: "always" }]强制文件扩展名规范
import/no-extraneous-dependencieserror{ devDependencies: [...] }禁止引入无关依赖
jsx-quoteserror"prefer-double"强制JSX属性使用双引号
react/jsx-boolean-valueerror["never", { always: [] }]禁止布尔属性显式值
react/jsx-closing-bracket-locationerror"line-aligned"闭合括号对齐规则
react/jsx-closing-tag-locationerror-闭合标签位置校验
react/jsx-curly-spacingerror["never", { allowMultiline: true }]禁止大括号内空格
react/jsx-indent-propserror2JSX属性缩进2空格
react/jsx-max-props-per-lineerror{ maximum: 1, when: "multiline" }每行最多1个属性(多行时)
react/jsx-no-binderror{ ignoreRefs: false, allowArrowFunctions: true }禁止JSX中不必要的函数绑定
react/jsx-no-duplicate-propserror{ ignoreCase: true }禁止重复属性
react/jsx-pascal-caseerror{ allowAllCaps: true, ignore: [] }强制组件帕斯卡命名
vue/jsx-uses-varserror-防止JSX变量未使用
vue/comment-directiveerror-强制Vue注释指令格式
vue/require-render-returnerror-要求render函数返回内容
react/self-closing-comperror-强制自闭合组件格式
react/jsx-wrap-multilineserror{ declaration: "parens-new-line" }多行JSX包裹格式
react/jsx-first-prop-new-lineerror"multiline-multiprop"多属性换行格式
react/jsx-equals-spacingerror"never"禁止等号周围空格
react/jsx-indenterror2JSX缩进2空格
react/jsx-no-target-blankerror{ allowReferrer: true }安全空白target校验
react/jsx-filename-extensionerror{ extensions: [".jsx", ".vue"] }限制JSX文件扩展名
react/jsx-no-comment-textnodeserror-禁止注释作为文本节点
react/style-prop-objecterror-强制style属性为对象
react/no-unescaped-entitieserror-禁止未转义HTML实体
react/no-children-properror-禁止直接传递children属性
react/jsx-tag-spacingerror{ closingSlash: "never" }标签空格规范
react/no-array-index-keyerror-禁止数组索引作为key
react/void-dom-elements-no-childrenerror-禁止void元素包含子元素
react/jsx-curly-brace-presenceerror{ props: "never" }禁止不必要的大括号
react/jsx-one-expression-per-lineerror{ allow: "single-child" }每行单个表达式
react/button-has-typeerror{ reset: false }强制按钮类型声明
react/jsx-props-no-multi-spaceserror-禁止属性多个空格
react/jsx-fragmentserror"syntax"强制使用简写片段语法
react/jsx-curly-newlineerror{ multiline: "consistent" }大括号换行一致性
react/jsx-props-no-spreadingerror{ html: "enforce" }限制属性展开使用
react/jsx-no-script-urlerror-禁止javascript: URL
react/jsx-no-useless-fragmenterror-禁止不必要的片段
react/no-namespaceerror-禁止命名空间组件
react/no-invalid-html-attributeerror-禁止无效HTML属性
jsx-a11y/accessible-emojioff-禁用表情可访问性校验
jsx-a11y/alt-texterror{ elements: [...] }强制替代文本
jsx-a11y/anchor-has-contenterror{ components: [] }锚点必须包含内容
jsx-a11y/anchor-is-validerror{ components: ["Link"] }锚点有效性校验
jsx-a11y/aria-activedescendant-has-tabindexerror-activeDescendant需要tabindex
jsx-a11y/aria-propserror-校验合法ARIA属性
jsx-a11y/aria-proptypeserror-ARIA属性类型校验
jsx-a11y/aria-roleerror{ ignoreNonDOM: false }校验合法ARIA角色
jsx-a11y/aria-unsupported-elementserror-禁止不支持ARIA的元素
jsx-a11y/autocomplete-validoff-禁用自动完成校验
jsx-a11y/click-events-have-key-eventserror-点击事件需对应键盘事件
jsx-a11y/control-has-associated-labelerror{ ignoreElements: [...] }控件需关联标签
jsx-a11y/heading-has-contenterror{ components: [""] }标题必须包含内容
jsx-a11y/iframe-has-titleerror-iframe必须包含标题
jsx-a11y/interactive-supports-focuserror-交互元素需可聚焦
jsx-a11y/label-has-associated-controloff-禁用标签关联控件校验
jsx-a11y/media-has-captionerror{ audio: [] }媒体元素需包含字幕
jsx-a11y/mouse-events-have-key-eventserror-鼠标事件需对应键盘事件
jsx-a11y/no-access-keyerror-禁止使用accessKey
jsx-a11y/no-autofocuserror{ ignoreNonDOM: true }禁止自动聚焦
jsx-a11y/no-distracting-elementserror{ elements: [...] }禁止干扰性元素
jsx-a11y/no-interactive-element-to-noninteractive-roleerror{ tr: [...] }交互元素角色限制
jsx-a11y/no-noninteractive-element-interactionserror{ handlers: [...] }非交互元素事件限制
jsx-a11y/no-noninteractive-element-to-interactive-roleerror{ ul: [...] }角色转换限制
jsx-a11y/no-noninteractive-tabindexerror{ roles: [...] }非交互元素tabindex限制
jsx-a11y/no-onchangeoff-禁用onChange校验
jsx-a11y/no-redundant-roleserror-禁止冗余ARIA角色
jsx-a11y/role-has-required-aria-propserror-角色需必要ARIA属性
jsx-a11y/role-supports-aria-propserror-ARIA属性与角色匹配
jsx-a11y/scopeerror-scope属性限制
jsx-a11y/tabindex-no-positiveerror-禁止正数tabindex
vue/max-lenerror[100, 2, { ignoreUrls: true }]行最大长度限制
vue/html-indenterror[2, { attribute: 1 }]HTML缩进规则
vue/max-attributes-per-lineerror{ multiline: { max: 1 } }每行最大属性数
vue/no-duplicate-attributeserror{ allowCoexistClass: true }禁止重复属性
vue/html-self-closingerror{ html: { void: "any" } }自闭合标签规则
vue/first-attribute-linebreakerror{ multiline: "below" }首属性换行规则
vue/no-spaces-around-equal-signs-in-attributeerror-属性等号无空格
vue/no-template-target-blankerror{ allowReferrer: true }安全target="_blank"校验
vue/no-child-contenterror-禁止子内容
vue/html-closing-bracket-spacingerror{ selfClosingTag: "always" }闭合括号空格规则
vue/html-button-has-typeerror{ reset: false }按钮类型声明
vue/no-multi-spaceserror-禁止多个空格
vuejs-accessibility/alt-texterror{ elements: [...] }可访问性替代文本
vuejs-accessibility/anchor-has-contenterror{ components: [] }锚点内容校验
vuejs-accessibility/aria-propserror-ARIA属性校验
vuejs-accessibility/aria-roleerror{ ignoreNonDOM: false }ARIA角色校验
vuejs-accessibility/aria-unsupported-elementserror-不支持ARIA的元素校验
vuejs-accessibility/click-events-have-key-eventserror-点击事件键盘支持
vuejs-accessibility/form-control-has-labelerror-表单控件标签关联
vuejs-accessibility/heading-has-contenterror-标题内容校验
vuejs-accessibility/iframe-has-titleerror-iframe标题校验
vuejs-accessibility/interactive-supports-focuserror-交互元素聚焦支持
vuejs-accessibility/label-has-forerror{ required: { some: [...] } }标签关联控件
vuejs-accessibility/media-has-captionerror-媒体字幕校验
vuejs-accessibility/mouse-events-have-key-eventserror-鼠标事件键盘支持
vuejs-accessibility/no-access-keyerror-禁止accessKey
vuejs-accessibility/no-autofocuserror{ ignoreNonDOM: true }禁止自动聚焦
vuejs-accessibility/no-distracting-elementserror{ elements: [...] }禁止干扰元素
vuejs-accessibility/no-onchangeoff-禁用onChange校验
vuejs-accessibility/no-redundant-roleserror-禁止冗余角色
vuejs-accessibility/role-has-required-aria-propserror-角色必要属性校验
vuejs-accessibility/tabindex-no-positiveerror-禁止正数tabindex
vue/require-default-properror-要求默认prop值
vue/no-potential-component-option-typoerror-组件选项拼写校验

基础规则 Vue

规则名称错误级别配置选项描述
vue/comment-directiveerror-强制 Vue 模板注释指令(如 <!-- eslint-disable -->)的正确使用,避免 ESLint 解析冲突。
vue/jsx-uses-varserror-防止在 Vue JSX 中使用的变量被 ESLint 误判为未使用,需配合变量引用检测。

优先级 A:必要的

规则名称错误级别配置选项描述
vue/multi-word-component-nameserror-强制组件名使用多单词,避免与HTML元素冲突
vue/no-arrow-functions-in-watcherror-禁止在watch中使用箭头函数(避免this指向问题)
vue/no-async-in-computed-propertieserror-禁止在计算属性中使用异步操作
vue/no-child-contenterror-禁止子组件使用content属性(已废弃)
vue/no-computed-properties-in-dataerror-禁止在data中引用计算属性
vue/no-deprecated-data-object-declarationerror-禁止使用已弃用的data对象声明方式
vue/no-deprecated-delete-seterror-禁止使用Vue.delete/Vue.set(Vue 3已内置)
vue/no-deprecated-destroyed-lifecycleerror-禁止使用已弃用的destroyed生命周期钩子(改用unmounted
vue/no-deprecated-dollar-listeners-apierror-禁止使用已弃用的$listeners API
vue/no-deprecated-dollar-scopedslots-apierror-禁止使用已弃用的$scopedSlots API
vue/no-deprecated-events-apierror-禁止使用已弃用的events API(Vue 3已移除)
vue/no-deprecated-filtererror-禁止使用已弃用的过滤器(Vue 3移除)
vue/no-deprecated-functional-templateerror-禁止使用已弃用的函数式模板语法
vue/no-deprecated-html-element-iserror-禁止使用已弃用的is属性语法(如<div is="...">
vue/no-deprecated-inline-templateerror-禁止使用已弃用的inline-template属性
vue/no-deprecated-model-definitionerror-禁止使用Vue 2风格的model选项定义
vue/no-deprecated-props-default-thiserror-禁止在propsdefault函数中使用this
vue/no-deprecated-router-link-tag-properror-禁止使用已弃用的<router-link>tag属性
vue/no-deprecated-scope-attributeerror-禁止使用已弃用的scope属性(改用slot-scope
vue/no-deprecated-slot-attributeerror-禁止使用已弃用的slot属性(改用v-slot
vue/no-deprecated-slot-scope-attributeerror-禁止使用已弃用的slot-scope属性(改用v-slot
vue/no-deprecated-v-bind-syncerror-禁止使用已弃用的.sync修饰符(Vue 3改用v-model参数)
vue/no-deprecated-v-iserror-禁止使用已弃用的v-is指令(改用is属性)
vue/no-deprecated-v-on-native-modifiererror-禁止使用已弃用的.native修饰符(Vue 3移除)
vue/no-deprecated-v-on-number-modifierserror-禁止在v-on指令中使用数字修饰符(如v-on:keyup.13
vue/no-deprecated-vue-config-keycodeserror-禁止使用已弃用的Vue.config.keyCodes
vue/no-dupe-keyserror-禁止在对象属性中重复键名
vue/no-dupe-v-else-iferror-禁止重复的v-else-if条件
vue/no-duplicate-attributeserror-禁止重复的属性声明
vue/no-export-in-script-setuperror-禁止在<script setup>中使用export
vue/no-expose-after-awaiterror-禁止在await后使用expose
vue/no-lifecycle-after-awaiterror-禁止在await后调用生命周期钩子
vue/no-mutating-propserror-禁止直接修改props
vue/no-parsing-errorerror-禁止模板解析错误
vue/no-ref-as-operanderror-禁止将ref直接作为操作数(需用.value
vue/no-reserved-component-nameserror-禁止使用保留的组件名(如HTML/SVG标签名)
vue/no-reserved-keyserror-禁止使用保留的键名(如$el$props等)
vue/no-reserved-propserror-禁止使用保留的props名称(如keyref等)
vue/no-shared-component-dataerror-禁止组件间共享数据对象(应使用函数返回)
vue/no-side-effects-in-computed-propertieserror-禁止计算属性产生副作用
vue/no-template-keyerror-禁止在<template>上使用key属性
vue/no-textarea-mustacheerror-禁止在<textarea>中使用双花括号插值
vue/no-unused-componentserror-禁止注册未使用的组件
vue/no-unused-varserror-禁止声明未使用的变量
vue/no-use-computed-property-like-methoderror-禁止像方法一样使用计算属性
vue/no-use-v-if-with-v-forerror-禁止在同一元素上同时使用v-ifv-for
vue/no-useless-template-attributeserror-禁止无效的模板属性(如非响应式属性)
vue/no-v-for-template-key-on-childerror-禁止在子组件上使用v-forkey
vue/no-v-text-v-html-on-componenterror-禁止在组件上使用v-text/v-html
vue/no-watch-after-awaiterror-禁止在await后调用watch
vue/prefer-import-from-vueerror-强制从vue导入API(而非直接访问Vue
vue/require-component-iserror-强制<component>元素使用is属性
vue/require-prop-type-constructorerror-强制props类型使用构造函数(如String而非'string'
vue/require-render-returnerror-强制render函数返回内容
vue/require-slots-as-functionserror-强制插槽以函数形式声明(兼容Vue 3)
vue/require-toggle-inside-transitionerror-强制在<transition>内使用v-show/v-if
vue/require-v-for-keyerror-强制v-for使用key属性
vue/require-valid-default-properror-强制propsdefault函数返回有效值
vue/return-in-computed-propertyerror-强制计算属性必须有return语句
vue/return-in-emits-validatorerror-强制emits验证函数返回布尔值
vue/use-v-on-exacterror-强制使用.exact修饰符处理精确按键事件
vue/valid-attribute-nameerror-强制属性名有效性(如不含空格)
vue/valid-define-emitserror-强制defineEmits宏的正确使用
vue/valid-define-optionserror-强制defineOptions宏的正确使用
vue/valid-define-propserror-强制defineProps宏的正确使用
vue/valid-next-tickerror-强制nextTick的正确使用
vue/valid-template-rooterror-强制模板根元素有效性(单元素/组件)
vue/valid-v-binderror-强制v-bind指令语法正确性
vue/valid-v-cloakerror-强制v-cloak指令无参数/值
vue/valid-v-else-iferror-强制v-else-if必须跟在v-if
vue/valid-v-elseerror-强制v-else必须跟在v-if/v-else-if
vue/valid-v-forerror-强制v-for指令语法正确性
vue/valid-v-htmlerror-强制v-html指令无参数
vue/valid-v-iferror-强制v-if指令语法正确性
vue/valid-v-iserror-强制v-is指令语法正确性
vue/valid-v-memoerror-强制v-memo指令语法正确性
vue/valid-v-modelerror-强制v-model指令语法正确性
vue/valid-v-onerror-强制v-on指令语法正确性
vue/valid-v-onceerror-强制v-once指令无参数/值
vue/valid-v-preerror-强制v-pre指令无参数/值
vue/valid-v-showerror-强制v-show指令语法正确性
vue/valid-v-sloterror-强制v-slot指令语法正确性
vue/valid-v-texterror-强制v-text指令无参数

优先级 B:强烈推荐

规则名称错误级别配置选项描述
vue/attribute-hyphenationwarn-强制组件属性名使用连字符格式(kebab-case)
vue/component-definition-name-casingwarn-强制组件定义名称的大小写(默认 PascalCase)
vue/first-attribute-linebreakwarn-控制第一个属性的换行位置
vue/html-closing-bracket-newlinewarn-强制闭合标签的括号换行格式
vue/html-closing-bracket-spacingwarn-强制闭合标签括号内外的空格规则
vue/html-end-tagswarn-要求 HTML 标签必须有闭合标签
vue/html-indentwarn-统一 HTML 元素的缩进规则
vue/html-quoteswarn-强制 HTML 属性值使用双引号
vue/html-self-closingwarn-强制自闭合标签的格式(无内容时自动闭合)
vue/max-attributes-per-linewarn-限制每行允许的最大属性数量
vue/multiline-html-element-content-newlinewarn-多行 HTML 元素内容前后需要换行
vue/mustache-interpolation-spacingwarn-强制 Mustache 插值内的空格规则
vue/no-multi-spaceswarn-禁止模板中出现连续多个空格
vue/no-spaces-around-equal-signs-in-attributewarn-属性等号周围禁止空格
vue/no-template-shadowwarn-禁止模板内变量与父作用域变量同名(避免遮蔽)
vue/one-component-per-filewarn-每个文件只能包含一个组件
vue/prop-name-casingwarn-强制 Prop 名称的格式(默认 camelCase)
vue/require-default-propwarn-要求 Prop 必须有默认值
vue/require-explicit-emitswarn-要求 emits 选项中明确声明触发的事件
vue/require-prop-typeswarn-要求 Prop 必须定义类型
vue/singleline-html-element-content-newlinewarn-单行 HTML 元素内容前后禁止换行
vue/v-bind-stylewarn-强制 v-bind 指令的简写或完整格式
vue/v-on-event-hyphenationwarn"always", { autofix: true }强制事件名使用连字符格式(kebab-case)
vue/v-on-stylewarn-强制 v-on 指令的简写或完整格式
vue/v-slot-stylewarn-强制 v-slot 指令的格式(默认缩写为 #

优先级 C:推荐

规则名称错误级别配置选项描述
vue/attributes-orderwarn-强制组件属性的顺序
vue/block-orderwarn-强制模板中块级元素的顺序
vue/no-lone-templatewarn-禁止没有内容的空模板标签
vue/no-multiple-slot-argswarn-禁止在作用域插槽中使用多个参数
vue/no-required-prop-with-defaultwarn-禁止在必需属性中设置默认值
vue/no-v-htmlwarn-禁止使用潜在危险的v-html指令
vue/order-in-componentswarn-强制组件选项的顺序
vue/this-in-templatewarn-禁止在模板中使用this上下文

Scoped CSS

eslint-plugin-vue-scoped-css 是一个用于检查和强制规范 Vue 单文件组件中作用域 CSS(<style scoped>)写法。

规则名称错误级别配置选项描述
vue-scoped-css/enforce-style-typewarn-强制 <style> 标签的 scoped 属性使用特定类型(如 scopedmodule
vue-scoped-css/no-deprecated-deep-combinatorwarn-禁止使用已弃用的深度选择器语法(如 >>>/deep/),推荐使用 ::v-deep
vue-scoped-css/no-parent-of-v-globalwarn-禁止在 ::v-global 伪类外再包裹其他选择器(因为 ::v-global 本身不应被限定在父选择器内)
vue-scoped-css/no-parsing-errorwarn-禁止由 vue-scoped-css 插件无法解析的 CSS 语法错误
vue-scoped-css/no-unused-keyframeswarn-禁止定义未使用的 @keyframes 动画
vue-scoped-css/no-unused-selectorwarn-禁止在 scoped 样式中定义未使用的选择器(这些选择器不会匹配任何元素)
vue-scoped-css/require-v-deep-argumentwarn-要求 ::v-deep 必须带有参数(例如 ::v-deep(.child)),除非用作组合器
vue-scoped-css/require-v-global-argumentwarn-要求 ::v-global 必须带有参数(例如 ::v-global(.global-class)
vue-scoped-css/require-v-slotted-argumentwarn-要求 ::v-slotted 必须带有参数(例如 ::v-slotted(.slot-class)