阅读 114

eslint及stylelint规则详解(持续更新)

前言:

已经有很多文章讲解eslint等工具的配置流程,不再赘述,可参考文章很多。 最近在系统的将以前的项目统一lint规范,修改了一些lint告警和错误,整理下来,仅供参考。 使用过程中能感受到standard是一套并不非常严格的规则,还是相对友好的。

我的配置

eslint扩展只配置了vue+standard

module.exports = {   root: true,   parserOptions: {     parser: "@babel/eslint-parser",     sourceType: "module"   },   env: {     es6: true,     node: true,     browser: true   },   extends: [     "plugin:vue/recommended",     "standard"   ],   plugins: [     "vue"   ],   rules: {   } } 复制代码

stylelint为scss扩展+recess-order+standard,后面会提加2条单独rules的原因。

 module.exports = {   extends: [     "stylelint-config-standard",     "stylelint-config-recess-order"   ],   plugins: [     "stylelint-scss"   ],   ignoreFiles: [     "**/*.{png,jpg,jpeg,gif,bmp,swf,svg,ico}",     "**/*.{ttf,woff,eot}",     "**/*.{yml,json}"   ],   rules: {     "at-rule-no-unknown": null,     "scss/at-rule-no-unknown": true   } } 复制代码

注释

  1. eslintrc文件中可配置规则on/off/0/1/2/error/warning等

  2. eslintignore中可配置想忽略的文件夹/文件

  3. 如果1,2不满足需求,想在具体代码中配置忽略,如下:

            /* eslint-disable */             var a =1,b=2             alert('foo');         /* eslint-enable */ 复制代码

    alert('foo'); // eslint-disable-line // eslint-disable-next-line alert('foo'); /* eslint-disable-next-line */ alert('foo'); alert('foo'); /* eslint-disable-line */ 复制代码

    alert('foo'); // eslint-disable-line no-alert, quotes, semi // eslint-disable-next-line no-alert, quotes, semi alert('foo'); alert('foo'); /* eslint-disable-line no-alert, quotes, semi */ /* eslint-disable-next-line no-alert, quotes, semi */ alert('foo'); 复制代码

    (场景举例:忽略对v-html的校验;需安装eslint-plugin-vue)

    <!-- eslint-disable-next-line -->

    <!-- eslint-disable-next-line vue/no-v-html -->

    • 在vue的节点中忽略某行dom中的es校验

    • 忽略某行代码的单个/多个规则,在上述基础上增加规则即可:

    • 忽略某行代码,以下4种均可

    • 忽略整个文件:文件首行增加 /* eslint-disable */

    • 忽略代码块:首尾增加disable和enable

stylelint忽略与eslint类似,不再赘述。

关于VUE扩展的强调

1.mixin文件需要在export default前增加一句// @vue/component使检测器将其视为组件。否则扩展对mixin文件不生效。详情查看eslint 或 github

2.在standrard的eslintrc和项目本地的eslintrc中,rules没有配置任何关于vue扩展的规则,使用的就是vue-recommend的默认规则配置.下图每个文件中的规则可访问官方文档

3.项目未配置任何关于vue3的lint扩展。参考链接

image.png

ESlint规则记录

eslint-base

中文规则网站竟然不全,wolegedacao,贴个英文规则

基于eslint规则官网的顺序逐一列出standard采用的规则。

Possible Errors

1.no-async-promise-executor禁止使用异步函数作为 Promise executor

new Promise 构造函数接收一个 executor 函数作为参数,该函数具有 resolve 和 reject 两个参数 禁止该参数为异步函数,不能带async。

2.no-compare-neg-zero禁止与 -0 进行比较 (听说过,没见过,没事不要写什么负0)

3.no-cond-assign 该规则禁止在 ifforwhile 和 do...while 语句中出现模棱两可的赋值操作符。(ex:如果在if判断中手滑少写了个等号,会报错)

4. no-constant-condition禁止在以下语句的条件中出现常量表达式:

  • ifforwhile 或 do...while 语句

  • ?: 三元表达式

if(0) if(true) 此类代码会报错

如下代码会同时触发3和4报错,首先使用了赋值单等号,赋值后成了常量。另:standard允许使用console,不允许有debugger

if (this.data = '') {   console.log('111') } 复制代码

5.no-control-regex 禁止在正则表达式中使用控制字符

在 ASCII 中,0-31 范围内的控制字符是特殊的、不可见的字符。这些字符很少被用在 JavaScript 字符串中,所以一个正则表达式如果包含这些字符的,很有可能一个错误。

const regx = /\x0D/    //回车符 console.log(regx) //error  Unexpected control character(s) in regular expression: \x0d  no-control-regex 复制代码

6. no-debugger 禁用debugger

7.no-dupe-args 禁止 function 定义中出现重名参数。 (ex: fucntion test(a,b,a) //error)

8. no-dupe-keys禁止对象字面量中出现重复的 key, 即禁止对象同名属性

(ex: var myObj = {name:'Jon',name:'Lucy'} //error

9.no-duplicate-case   switch case结构中,不允许有重复的case值

10.no-empty 禁止空代码块,会忽略包含一句注释的代码块。

standard配置为"no-empty": ["error", { "allowEmptyCatch": true }], 额外允许空的catch块

11. no-empty-character-class 禁止正则表达式中出现空字符集  (ex:/^abc[]/ 匹配个寂寞)

12.no-ex-assign禁止对catch的error重新赋值

13.no-extra-boolean-cast禁止不必要的布尔转换(auto fix

if(!!this.passWord)会被自动修复为if(this.passWord) if语句会自动做布尔转换,手动多余

14.no-extra-parens禁止多余的圆括号(auto fix) standard配置为"no-extra-parens": ["error", "functions"] 即允许函数周围多余的括号。

ex: typeof (a) 会被自动修复为typeof a

15.no-func-assign禁止对函数声明重新赋值

16. no-import-assign禁止对import的变量重新赋值

import mod, { named } from "./mod.mjs" import * as mod_ns from "./mod.mjs" //错误举例 mod = 1          // ERROR: 'mod' is readonly. named = 2        // ERROR: 'named' is readonly. mod_ns.named = 3 // ERROR: the members of 'mod_ns' is readonly. mod_ns = {}      // ERROR: 'mod_ns' is readonly. //推荐举例 mod.prop = 1 named.prop = 2 mod_ns.named.prop = 3 // Known Limitation function test(obj) {     obj.named = 4 // Not errored because 'obj' is not namespace objects. } test(mod_ns) // Not errored because it doesn't know that 'test' updates the member of the argument. 复制代码

17.no-invalid-regexp禁止在 RegExp 构造函数中出现无效的正则表达式。 这条报错很难单独出现。因为经常和另一条规则 prefer-regex-literals 一起出现。 正则创建形式:

/ab+c/i; //字面量形式 new RegExp('ab+c', 'i'); // 首个参数为字符串模式的构造函数 new RegExp(/ab+c/, 'i'); // 首个参数为常规字面量的构造函数 复制代码

单独触发no-invalid-regexp:

const flag = 'i' const a = new RegExp('[', flag) console.log(a) 复制代码

如果使用let b = /[/ let c=/'['/这种字面量形式,解析器会直接报语法错误,但在RegExp构造函数中不会报错,所以增加了这条规则。但是很少有人这样单独定义flag和pattern来写正则,完全没有必要。如果不单独声明flag和pattern,会触发另一条规则 prefer-regex-literals  standard的配置是 ["error", { "disallowRedundantWrapping": true }], 禁止构造函数中只使用字面量,多余的//包裹也会报错。

综上:除非使用动态的正则,优先采用字面量形式创建。

18.no-irregular-whitespace禁止不规则的空白。由于在Stylistic Issues风格指南中规定了各种空格规则且会自动fix,之后不会触发此规则。

19.no-loss-of-precision禁止丢失精度的数字 基础知识补一补

20. no-misleading-character-class 禁止在字符类语法中出现由多个代码点组成的字符 基础知识再补一补

21.no-obj-calls禁止把全局对象作为函数调用

错误 代码示例:

/*eslint no-obj-calls: "error"*/ var math = Math(); var json = JSON(); var reflect = Reflect(); 复制代码

正确 代码示例:

/*eslint no-obj-calls: "error"*/ function area(r) {     return Math.PI * r * r; } var object = JSON.parse("{}"); var value = Reflect.get({ x: 1, y: 2 }, "x"); 复制代码

22. no-prototype-builtins禁止直接调用 Object.prototypes 的内置属性。

错误 代码示例:

/*eslint no-prototype-builtins: "error"*/ var hasBarProperty = foo.hasOwnProperty("bar"); var isPrototypeOfBar = foo.isPrototypeOf(bar); var barIsEnumerable = foo.propertyIsEnumerable("bar"); 复制代码

正确 代码示例:

/*eslint no-prototype-builtins: "error"*/ var hasBarProperty = Object.prototype.hasOwnProperty.call(foo, "bar"); var isPrototypeOfBar = Object.prototype.isPrototypeOf.call(foo, bar); var barIsEnumerable = {}.propertyIsEnumerable.call(foo, "bar"); 复制代码

23.no-regex-spaces禁止正则表达式字面量中出现多个空格(auto fix

24. no-sparse-arrays 禁用稀疏数组 错误示例: var items = [,]; var colors = [ "red",, "blue" ];

25. no-template-curly-in-string 禁止在常规字符串中出现模板字面量占位符语法,

即不允许var msg = "Hello ${name}!"之类的写法

  1. no-unexpected-multiline禁止出现令人困惑的多行表达式。看举例更方便明白意图。

错误 代码示例:

/*eslint no-unexpected-multiline: "error"*/ var foo = bar (1 || 2).baz(); var hello = 'world' [1, 2, 3].forEach(addNumber); let x = function() {} `hello` let x = function() {} x `hello` let x = foo /regex/g.test(bar) 复制代码

正确 代码示例:

/*eslint no-unexpected-multiline: "error"*/ var foo = bar; (1 || 2).baz(); var foo = bar ;(1 || 2).baz() var hello = 'world'; [1, 2, 3].forEach(addNumber); var hello = 'world' void [1, 2, 3].forEach(addNumber); let x = function() {}; `hello` let tag = function() {} tag `hello` 复制代码

27. no-unreachable禁止在 returnthrowcontinue 和 break 语句之后出现不可达代码

28. no-unreachable-loop 禁止最多可进行一次迭代的循环。如在循环中写一定执行的break,如下错误示例

for (foo of bar) {     if (foo.id === id) {         doSomething(foo);     }     break; } 复制代码

29.no-unsafe-finally禁止在 finally 语句块中出现控制流语句。JavaScript 暂停 try 和 catch 语句块中的控制流语句,直到 finally 语句块执行完毕。所以,当 returnthrowbreak 和 continue 出现在 finally 中时, try 和 catch 语句块中的控制流语句将被覆盖,这被认为是意外的行为。

30.no-unsafe-negation 禁止对关系运算符的左操作数使用否定操作符 (auto fix) 该规则禁止对关系运算符的左操作数使用否定操作符。

关系运算符有:

  • in 运算符.

  • instanceof 运算符.

错误 代码示例:

/*eslint no-unsafe-negation: "error"*/ if (!key in object) {     // operator precedence makes it equivalent to (!key) in object     // and type conversion makes it equivalent to (key ? "false" : "true") in object } if (!obj instanceof Ctor) {     // operator precedence makes it equivalent to (!obj) instanceof Ctor     // and it equivalent to always false since boolean values are not objects. } 复制代码

正确 代码示例:

/*eslint no-unsafe-negation: "error"*/ if (!(key in object)) {     // key is not in object } if (!(obj instanceof Ctor)) {     // obj is not an instance of Ctor } if(("" + !key) in object) {     // make operator precedence and type conversion explicit     // in a rare situation when that is the intended meaning } 复制代码

31.no-useless-backreference  禁止在正则表达式中使用无用的反向引用,没仔细研究

32. use-isnan  ["error", {"enforceForSwitchCase": true, "enforceForIndexOf": true}], 禁止在各种判断的地方直接使用NaN,必须使用isNaN来判断,包括switch case分支和indexOf

33. valid-typeof ["error", { "requireStringLiterals": true }] typeof只能与typeof预期的几个字符串结果比较

Best Practices

1. accessor-pairs ["error", { "setWithoutGet": true, "enforceForClassMembers": true }],强制 getter 和 setter 在对象中成对出现 ,但只有setter不报错,报warning。enforceForClassMembers对class中的get,set也生效.

eslint-plugin-vue

1. vue/require-default-prop warning  Prop 'clientType' requires default value to be set

2.  vue/require-prop-type-constructor error The "clientType" property should be a constructor

props: {     clientType: ''   }, 复制代码

针对props,要求有默认值且type为构造函数,修改如下

props: {     clientType: {       default: '',       type: String     }   }, 复制代码

如果为对象,如下写法将触发报错3

props: {     clientType: {       default: '',       type: Object     }   }, 复制代码

3. vue/require-valid-default-prop  error  Type of the default value for 'clientType' prop must be a function
此规则检查对于给定的type,default是否有效。Arrary和Object的default必须是函数。修改如下:

props: {       clientType: {           type: Object,           default() {             return { message: 'hello' }           }       }     }, 复制代码

4. vue/no-use-v-if-with-v-for vue对v-for的处理优先级高,导致每次循环都会执行一遍v-if,目前项目中有大量的v-if和v-for放在一个节点上,实实在在的影响了执行效率.推荐外层增加一层template使用v-if

<ul v-if="complete">      <TodoItem v-for="todo in todos" :todo="todo" /> </ul> 复制代码

eslint-plugin-node

standrd配置了如下7条

1."node/handle-callback-err": ["error", "^(err|error)$" ] 一定要处理回调函数的error或err参数

以^开头表示正则匹配

  • 如果选项是"^(err|error|anySpecificError)$",则规则报告参数名称可以是err,error或 的未处理错误anySpecificError

  • 如果选项为"^.+Error$",则规则报告参数名称以Error(例如,connectionErrorvalidationError将匹配)结尾的未处理错误。

  • 如果选择是"^.*(e|E)rr",该规则报告,其中的参数名称中包含任何字符串匹配未处理的错误errErr(例如errerroranyErrorsome_err将匹配)。

//如下回调函数传参为data,不报错。reject特意传参new Error()是因为有另一条规则 //Expected the Promise rejection reason to be an Error  prefer-promise-reject-errors function (data) {     return Promise.reject(new Error())   })    //把data改为err或error,同样不使用,会报错  Expected error to be handled  node/handle-callback-err  function (error) {     return Promise.reject(new Error())   }) 复制代码

2."node/no-callback-literal": "error" 调用名为cb或callback的函数时,第一个参数不能为字面量

/*如下代码会触发报错触发报错  error  Unexpected literal in error position of callback  node/no-callback-literal*/ mounted () {     function callback (a) {       console.log(a)     }     callback('a')   },  //注:在methods里定义callback(){}, this.callback('字面量')不会报错      /*不报错的调用*/ cb(undefined); cb(null, 5); callback(new Error('some error')); callback(someVariable); 复制代码

3."node/no-deprecated-api": "error"   禁用废弃的node api

  //例如 url.prase废弃,推荐改为如下写法   let params = (new URL(window.location)).searchParams;   let.get('lang') 复制代码

4."node/no-exports-assign": "error" 应该是不许给export直接赋值

???? Examples of **correct** code for this rule: /*eslint node/no-exports-assign: error */ module.exports.foo = 1 exports.bar = 2 module.exports = {} // allows `exports = {}` if along with `module.exports =` module.exports = exports = {} exports = module.exports = {} ???? Examples of **incorrect** code for this rule: /*eslint node/no-exports-assign: error */ exports = {} 复制代码

5."node/no-new-require": "error" 禁止new关键字和require一起使用

//不推荐 var appHeader = new require('app-header'); //推荐 var AppHeader = require('app-header'); var appHeader = new AppHeader(); 复制代码

6."node/no-path-concat": "error" 禁止带正反斜杠的字符串连接__dirname__filename(不完全确定)

开发人员可能会尝试使用这些变量来创建其他文件的路径,例如:

var  fullPath  =  __dirname  +  "/index.js" ; 复制代码

这种方式,需要配合运行的操作系统判断的代码,官方不推荐,应使用path模块的join或resolve

var fullPath1 = path.resolve(__dirname, "index.js"); var fullPath2 = path.join(__dirname, "index.js"); 复制代码

报错写法举例

/*eslint node/no-path-concat: "error"*/ const fullPath1 = __dirname + "/foo.js"; const fullPath2 = __filename + "/foo.js"; const fullPath3 = `${__dirname}/foo.js`; const fullPath4 = `${__filename}/foo.js`; 复制代码

正确写法举例

const fullPath1 = path.join(__dirname, "foo.js"); const fullPath2 = path.join(__filename, "foo.js"); const fullPath3 = __dirname + ".js"; const fullPath4 = __filename + ".map"; const fullPath5 = `${__dirname}_foo.js`; const fullPath6 = `${__filename}.test.js`; 复制代码

7."node/process-exit-as-throw": "error"

执行--fix能自动修复的规则列表

no-extra-boolean-cast禁止不必要的布尔转换

no-regex-spaces禁止正则表达式字面量中出现多个空格

no-extra-parens禁止多余的圆括号(auto fix)standard配置为"no-extra-parens": ["error", "functions"] 即允许函数周围多余的括号。

no-unsafe-negation 禁止对关系运算符的左操作数使用否定操作符

standard未采用的eslint规则

for-direction

getter-return

no-await-in-loop

no-console

no-extra-semi standard配置了无分号,覆盖此规则

no-inner-declarations禁止在嵌套的语句块中声明函数

no-dupe-else-if 禁止else if分支条件重复

no-promise-executor-return

no-setter-return

no-unsafe-optional-chaining

中文站缺失的规则

no-dupe-else-if 禁止else if分支条件重复

no-import-assign

no-loss-of-precision

no-promise-executor-return

此规则的错误代码示例:

/*eslint no-promise-executor-return: "error"*/ new Promise((resolve, reject) => {     if (someCondition) {         return defaultResult;     }     getSomething((err, result) => {         if (err) {             reject(err);         } else {             resolve(result);         }     }); }); new Promise((resolve, reject) => getSomething((err, data) => {     if (err) {         reject(err);     } else {         resolve(data);     } })); new Promise(() => {     return 1; }); 复制代码

此规则的正确代码示例:

/*eslint no-promise-executor-return: "error"*/ new Promise((resolve, reject) => {     if (someCondition) {         resolve(defaultResult);         return;     }     getSomething((err, result) => {         if (err) {             reject(err);         } else {             resolve(result);         }     }); }); new Promise((resolve, reject) => {     getSomething((err, data) => {         if (err) {             reject(err);         } else {             resolve(data);         }     }); }); Promise.resolve(1); 复制代码

no-setter-return

no-unreachable-loop

no-unsafe-optional-chaining 禁止在不允许使用undefined值的上下文中使用可选链. 可选的链接 ( ?.) 表达式可以短路,返回值为undefined。因此,将评估的可选链接表达式视为函数、对象、数字等,可能会导致 TypeError 或意外结果。例如:

var obj = undefined; 1 in obj?.foo;  // TypeError with (obj?.foo);  // TypeError for (bar of obj?.foo);  // TypeError bar instanceof obj?.foo;  // TypeError const { bar } = obj?.foo;  // TypeError 复制代码

此外,括号限制了链中短路的范围。例如:

var obj = undefined; (obj?.foo)(); // TypeError (obj?.foo).bar; // TypeError 复制代码

no-useless-backreference


作者:断笔画墨
链接:https://juejin.cn/post/7022140705950662693


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐