如何使用私有方法正确配置 ES6 类的 eslint?

Posted

技术标签:

【中文标题】如何使用私有方法正确配置 ES6 类的 eslint?【英文标题】:How to configure eslint for ES6 class with private methods correctly? 【发布时间】:2020-04-29 23:12:42 【问题描述】:

我在 vue 项目中使用私有属性/方法编写 ES6 类。并使用 eslint 对代码进行 lint。下面是示例类:

class TestClass 
  constructor(value) 
    this.#privateProperty = value
    this.#privateMethod(this.#privateProperty)
  

  #privateProperty = undefined

  // lint error raised at below line
  #privateMethod(value) 
    this.e = value
    console.log(this.e)
  

vue 项目由@vue/cli 4.1.2 创建。以下是有关该项目的一些配置:

babel.config.js:

module.exports = 
  presets: ['@vue/cli-plugin-babel/preset'],
  plugins: [
    ['@babel/plugin-proposal-class-properties',  loose: true ],
    ['@babel/plugin-proposal-private-methods',  loose: true ]
  ]

package.json:


  "name": "demo-project",
  "version": "0.1.0",
  "private": true,
  "scripts": 
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "test:unit": "vue-cli-service test:unit",
    "lint": "vue-cli-service lint"
  ,
  "dependencies": 
    "axios": "^0.19.0",
    "cesium": "^1.64.0",
    "core-js": "^3.4.4",
    "mockjs": "^1.1.0",
    "vue": "^2.6.10",
    "vue-router": "^3.1.3",
    "vuex": "^3.1.2"
  ,
  "devDependencies": 
    "@babel/plugin-proposal-private-methods": "^7.8.0",
    "@vue/cli-plugin-babel": "^4.1.0",
    "@vue/cli-plugin-eslint": "^4.1.0",
    "@vue/cli-plugin-router": "^4.1.0",
    "@vue/cli-plugin-unit-jest": "^4.1.0",
    "@vue/cli-plugin-vuex": "^4.1.0",
    "@vue/cli-service": "^4.1.0",
    "@vue/eslint-config-prettier": "^5.0.0",
    "@vue/test-utils": "1.0.0-beta.29",
    "babel-eslint": "^10.0.3",
    "copy-webpack-plugin": "^5.1.1",
    "eslint": "^5.16.0",
    "eslint-plugin-prettier": "^3.1.1",
    "eslint-plugin-vue": "^5.0.0",
    "lint-staged": "^9.5.0",
    "node-sass": "^4.12.0",
    "prettier": "^1.19.1",
    "sass-loader": "^8.0.0",
    "vue-template-compiler": "^2.6.10",
    "webpack": "^4.41.5"
  ,
  "gitHooks": 
    "pre-commit": "lint-staged"
  ,
  "lint-staged": 
    "*.js,vue": [
      "vue-cli-service lint",
      "git add"
    ]
  

.eslintrc.js

module.exports = 
  root: true,
  env: 
    node: true
  ,
  extends: ["eslint:recommended", "plugin:vue/recommended", "@vue/prettier"],
  rules: 
    "no-console": process.env.NODE_ENV === "production" ? "error" : "off",
    "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off"
  ,
  parserOptions: 
    parser: "babel-eslint"
  ,
  overrides: [
    
      files: [
        "**/__tests__/*.j,ts?(x)",
        "**/tests/unit/**/*.spec.j,ts?(x)"
      ],
      env: 
        jest: true
      
    
  ],
  globals: 
    'process': true
  
;

问题是 eslint 总是在 #privateMethod 的标签上引发 lint 错误 Parsing error: This experimental syntax requires enabling the parser plugin: 'classPrivateMethods'

我用谷歌搜索了很多,但没有找到我错过了什么。

请帮忙,非常感谢。

【问题讨论】:

【参考方案1】:

      好的,所以我来这里分享我学到的东西,因为我花了一段时间才找到它。看上面的配置文件图片,看起来你是通过为你寻求的支持实现单独的规则来做的,但是,有一个 Babel Preset NPM Package 使它成为所有 ECMAS 阶段-支持3个提案,配置少很多,你只需要知道怎么做,这就是我写这篇文章的原因。首先我想说的是,我现在可以告诉你,这不是一个简短的回答。要解释所需的过程,我需要一些打字和努力。这么多指南未能成功帮助人们让 babel 与 ESLint 同步工作的一个原因是,用文本解释解决方案需要一些时间。虽然一旦解释了,你会发现,它非常简单。


我们开始:

首先您需要确保您有 ESLint,所以请继续执行以下操作。

:~$ npm init
:~$ npm i -D eslint
:~$ eslint --init 

        希望您熟悉上述命令。如果你不是,那么你需要先去学习如何配置 ESLint。此时,您应该有一个新的 eslintrc.json 文件(或 YAML 等效文件),它是无规则且无插件的。它可能扩展了 Google 或 Airbnb(我使用 Google 的 JS 样式指南,但没关系)。如果 NPM 包文件,你也应该有一个新的集合,尽管我们不会使用它们。现在我们将安装 BABEL。 Babel,真的进步了。过去配置 Babel 是很困难的 IMO,但现在他们有一个预设模块,它使配置 Babel 变得更加简单。


您需要下载 4 个 NPM 包:

      您需要的所有 Babel 模块都作为单独的 npm 包发布在 @babel 下(从版本 7 开始)。这种模块化设计允许使用各种工具,每种工具都针对特定用例而设计。这里我们看看@babel/core

                       -- BabelJS.io

      需要完成 NPM 的四个下载才能获得对 Private Members 和其他 ECMAScript Stage-3 提案的支持:

    通天塔本身

    Babel 配置模块(让生活更轻松)

    Babels ESLint 插件

    用于 ESLint 的 Babel-Parser

      为了给这个答案提供最佳机会,为您提供所需的解决方案,我将分别浏览每个 NPM 模块,并为您提供文档链接,以防出现问题。每个开发环境都各不相同,这种配置可以而且很可能会非常适合您使用的开发环境。例如,在我切换 ESLint 正在使用的解析器后,我使用 prettier 进行格式化,这带来了另一组挑战以使其正常工作。如果你使用资源提出来。没有理由不能让 Babel 与 eslint 一起工作,并正确配置 ESLint,以便 Private-Members 和所有其他 Stage-3 ECMAScript 提案在您对文档进行 lint 时不会出现错误。


(NPM DL #1)

安装 Babel:

    为了获取 BABEL 将以下命令复制并粘贴到您的终端中。

:~$ npm i -D @babel/core 

      Babel/core 是不言自明的,因为 Babel 的核心功能位于 @babel/core 模块的核心。

Official Babel Core Package Documentation

(NPM DL #2)

安装 Babel 的预设模块

:~$ npm i -D @babel/preset-env

      无需任何配置,此预设将包含所有支持现代 javascript 的插件。它还包括对所有阶段 3 ECMAScript 提案的支持。导致我们需要 Babel 解析器的整个问题是 ESLint 的默认解析器和核心规则只支持最新的最终 ECMAScript 标准语法,不支持实验性语法。

Official @babel/preset-env Documentation

(NPM DL #3)

为 ESLint 安装 Babel Parser


:~$ npm i -D @babel/eslint-parser

      ESLint 允许使用自定义解析器。当使用这个插件时,你的代码会被 Babel 的解析器解析(使用在你的 Babel 配置文件中指定的配置)并且生成的 AST(对于那些不知道 AST 是抽象语法树的人)被转换成符合 ESTree 的结构ESLint 可以理解的。所有位置信息(如行号、列)也会保留,以便您轻松追踪错误。

注意: ESLint 的核心规则不支持实验性语法,因此在使用 @babel/eslint-parser 时可能无法按预期工作。请使用配套的 @babel/eslint-plugin 插件来解决您遇到问题的核心规则。

                       -- Babel-ESLint-Parser README.md 文档

Babel/ESLint Parser README.md Document

(NPM DL #4)

安装 Babel 的 ESLint 插件:

:~$ npm i -D @babel/eslint-plugin

      @babel/eslint-parser 的伴随规则。 @babel/eslint-parser 在调整 eslint 以与 Babel 一起使用方面做得很好,但它无法更改内置规则以支持实验性功能。 @babel/eslint-plugin 重新实现了有问题的规则,因此它们不会给出误报或否定。

                          - @babel/eslint-plugin 存储库

Babel-ESLint-Plugin Repository's README.md Document

以下内容已弃用,因此错误!

npm install eslint babel-eslint --save-dev

      如果您看到使用上述解决方案的解决方案,或任何其他 NPM 包名称中没有 "@babel/..." 的 NPM 包,则该解决方案已被弃用,并且可能不会工作。


配置“.babelrc”和“.eslintrc”文件

首先我会告诉你.eslintrc文件应该是什么样子,并通过cmets进行解释。


  "env": 
    //  Make sure your environment is configured properly
    "es2021": true,
    "commonjs": true,
    "node": true,
    "browser": false
  ,

  "extends": ["google"],
  "plugins": [
    "prettier",
    "@babel" // This is where you inform ESLint that you want to use @babel/eslint-plugin. If you have other plugins use an array.
  ],

  "parser": "@babel/eslint-parser", // He is where you communicate to ESLint that you want to use the @babel/eslint-parser.

  "parserOptions": 
    "ecmaVersion": 2021, // 12 or 2021 is the most current ECMAS Version

    "sourceType": "module", // For use with JS Modules set to module, otherwise it can be set to script

    "allowImportExportEverywhere": false, // When set to true this configuration allows import and export declarations to be placed where ever a statement can be made. Obviously your Env must support the Dynamic placement of the import/export statements for it to work.

    "ecmaFeatures": 
      "globalReturn": false // allow return statements in the global scope when used with sourceType: "script".
    
    
  ,

  "rules": 
    "require-jsdoc": "off",
    "arrow-body-style": "off",
    "prefer-arrow-callback": "off",
    "no-unused-expressions": "warn",
    "no-unused-vars": "warn",

    // These are all the rules that Babel-Plugin has support for. If the plugin will implement a rule, you should have it do so instead of using ESLint's equal rule.
    "@babel/new-cap": "error",
    "@babel/no-invalid-this": "error",
    "@babel/no-unused-expressions": "error",
    "@babel/object-curly-spacing": "error",
    "@babel/semi": "error",

    /* 
    I Omitted this rule because @Babel-Plugin offers this rule. 
    "semi": ["error", "always"],    */
   
  


我们终于可以创建一个“.babelrc”文件了!

我不知道我们在这个答案中所做的一切背后的所有机制,我不会假装知道。大约 8 个月前,我在使用 Babel 做其他事情时尝试让 .babelrc 文件工作,但我做不到。我不得不使用 babelrc.js。由于某种原因,我正在解释的配置使得我们必须使用的文件是.babelrc,这让我很高兴。

话虽如此,在您的项目根目录中创建文件.babelrc。创建“...ProjectRoot/.babelrc”配置文件后,这个答案的其余部分非常简单,如下所示。

在您的 .babelrc 文件中粘贴以下内容:

  "presets": [
    [
      "@babel/preset-env",
      
        "shippedProposals": true,
        "ignoreBrowserslistConfig": true
      
    ]
  ]


就是这样!


如果这个答案没有让 Babel 与 eslint 合作,能够对私有类成员或其他 ECMAS Stage-3 提案进行 lint,请在下面给我发消息或发表评论,我会保证回复。

就是这样!

【讨论】:

这对我有用。谢谢。一件事:编辑您的答案,以便包含安装@babel/eslint-parser 的命令,看来您忘记输入了。 @spaceinvadev 哦,好吧,会的。如果您注意到它,您可以随时编辑类似的内容。您不必这样做,但它肯定是一个适当的回应。【参考方案2】:

你只需要安装 babel-eslint 版本 v11.0.0-beta.0,但是你可以看到它的 beta 版本,但这应该适用于这种语法。

【讨论】:

我已经尝试过它和其他两个版本(beta.1 和 beta.2)。他们都有相同的BUG#749。 是的,我刚刚注意到,这个问题#749 与babel 相关,不确定这是否会很快可用,您的项目中是否需要它?

以上是关于如何使用私有方法正确配置 ES6 类的 eslint?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Traceur 在 ES6 类中实现私有方法 [重复]

ES6 class类中定义私有变量

js类的继承,es5和es6的方法

ES6 Class 基础语法

ES6 模块:导出单个类的静态方法或多个单独的方法

如何从 Swift 扩展访问 Objective-C 类的私有成员?