Eslint自定义规则使用

文章目录


前言

设计一个非常真实、非常有价值的自定义规则场景,这个场景在开发中都可能遇到的:架构约束规则


场景设定:维护代码分层,禁止"跨级调用"

背景

在一个良好分层的项目中,我们通常会把代码分成不同的层次。假设你的 uni-app 项目遵循以下结构:

  • src/services/:存放所有与后端 API 交互的逻辑(比如 userService.ts, productService.ts)。这些是"数据服务层"。
  • src/pages/:存放所有的页面(.vue 文件)。这些是"视图层"。
  • src/utils/:存放通用的工具函数。

团队规定(我们的架构约束)

为了保持代码的清晰和可维护性,团队规定 "视图层 (pages)" 不允许直接调用 "数据服务层 (services)"

  • 错误的做法 :在 src/pages/my/index.vue 中直接 import { getUserInfo } from '@/services/userService';
  • 正确的做法 :页面应该通过一个统一的、更高层的逻辑单元(比如 Vuex/Pinia 的 actions,或者一个专门的 controller 层)来获取数据,而不是直接触碰底层的 service。

目标

我们要创建一个自定义 ESLint 规则,叫做 no-service-import-in-pages。当有开发者试图在 src/pages/ 目录下的任何文件中导入 src/services/ 里的模块时,ESLint 应该立刻用红色下划线报错,并给出清晰的提示:"页面组件不允许直接导入 service,请通过状态管理层调用。"


实现步骤:从零到一,创建你的第一条自定义规则

这个过程分为两步:1. 编写规则2. 注册规则

第 1 步:创建规则文件
  1. 在你的项目根目录(和 package.json 同级)创建一个新文件夹,命名为 eslint-rules

  2. 在这个文件夹里,创建一个新文件,命名为 no-service-import-in-pages.js

  3. 将以下代码粘贴到 no-service-import-in-pages.js 中:

    javascript 复制代码
    /**
     * @fileoverview Rule to prevent importing from the services layer directly into page components.
     * @author Your Name
     */
    "use strict";
    
    //------------------------------------------------------------------------------
    // Rule Definition
    //------------------------------------------------------------------------------
    
    module.exports = {
      // meta: 包含了规则的元数据
      meta: {
        type: "problem", // 这表示规则将发现一个代码问题
        docs: {
          description: "Disallow direct imports from the services layer in page components",
          category: "Best Practices",
          recommended: true,
        },
        fixable: null, // 这个规则不可自动修复
        schema: [], // 这个规则没有额外的配置选项
        messages: {
            noServiceImport: "页面组件不允许直接导入 service,请通过状态管理层调用。",
        }
      },
    
      // create: 返回一个对象,这个对象包含了遍历 AST 时要访问的节点
      create(context) {
        // 获取当前正在被检查的文件的绝对路径
        const filename = context.getFilename();
    
        // 如果文件路径不包含 /pages/,那么这个规则直接跳过,不进行任何检查
        if (!filename.includes("/src/pages/")) {
          return {};
        }
    
        // 如果文件在 pages 目录下,我们返回一个访问者对象
        return {
          // 'ImportDeclaration' 是 AST 中代表 'import ... from ...' 语句的节点类型
          ImportDeclaration(node) {
            // node.source.value 获取的是 from 后面的字符串,比如 '@/services/userService'
            const importSource = node.source.value;
    
            // 检查这个导入路径是否包含了 'services'
            if (importSource && importSource.includes("services")) {
              // 如果包含了,就报告一个错误
              context.report({
                node: node, // 在这个 import 语句节点上报告错误
                messageId: "noServiceImport", // 使用 meta.messages 中定义好的错误信息
              });
            }
          },
        };
      },
    };
第 2 步:在 eslint.config.mjs 中注册并启用你的规则

现在我们需要告诉 ESLint:"嘿,我写了一个新规则,给你用!"

打开 eslint.config.mjs,我们需要修改 "3. A main configuration object" 这个部分,添加一个新的 plugins 字段,并启用我们的规则。

javascript 复制代码
// ... 其他 import 语句 ...
// 导入我们自己的规则
import noServiceImportInPages from './eslint-rules/no-service-import-in-pages.js';

export default [
  // ... 其他配置 ...

  // 3. A main configuration object for our custom settings
  {
    languageOptions: {
      // ... globals ...
    },
    plugins: {
      // Make plugins available for all files
      '@typescript-eslint': tseslint.plugin,
      vue: vuePlugin,
      // 在这里注册我们的自定义规则插件
      'custom-rules': {
        rules: {
          'no-service-import-in-pages': noServiceImportInPages,
        },
      },
    },
    rules: {
      // ... 其他规则 ...
      // 在这里启用我们的自定义规则,并设置为 error 级别
      'custom-rules/no-service-import-in-pages': 'error',
    },
  },

  // ... 其他配置 ...
];

验证成果

做完以上修改后,请重启 VSCode!

现在,去任何一个位于 src/pages/ 目录下的 .vue 文件,在 <script> 标签里尝试写下:

typescript 复制代码
import { someFunction } from '@/services/api';

你会立刻看到,这行代码被画上了红色波浪线,当你把鼠标悬停在上面时,会显示我们自定义的错误信息:"页面组件不允许直接导入 service,请通过状态管理层调用。"

而在 src/utils 或其他非 pages 目录的文件中进行同样的导入,则不会有任何报错。

就这样成功地创建并应用了一条非常有价值的、用于维护项目架构的自定义 ESLint 规则!

相关推荐
用户0328472220704 小时前
如何搭建本地yum源(上)
运维
大树883 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠3 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质3 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
小宇宙Zz3 天前
Maven依赖冲突
java·服务器·maven
Inhand陈工3 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智3 天前
ARP代理--工作原理
运维·网络·arp·arp代理
shushangyun_3 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
古城小栈3 天前
Unix 与 Linux 异同小叙
linux·服务器·unix
施努卡机器视觉3 天前
SNK施努卡侧滑门锁上滑轮总成自动化装配线,从零件到组件,全流程精密制造方案
运维·自动化·制造