文章目錄
- 前言
- 場景設定:維護代碼分層,禁止“跨級調用”
- 實現步驟:從零到一,創建你的第一條自定義規則
- **第 1 步:創建規則文件**
- **第 2 步:在 `eslint.config.mjs` 中注冊并啟用你的規則**
- 驗證成果
前言
設計一個非常真實、非常有價值的自定義規則場景,這個場景在開發中都可能遇到的:架構約束規則。
場景設定:維護代碼分層,禁止“跨級調用”
背景:
在一個良好分層的項目中,我們通常會把代碼分成不同的層次。假設你的 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 步:創建規則文件
-
在你的項目根目錄(和
package.json
同級)創建一個新文件夾,命名為eslint-rules
。 -
在這個文件夾里,創建一個新文件,命名為
no-service-import-in-pages.js
。 -
將以下代碼粘貼到
no-service-import-in-pages.js
中:/*** @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
字段,并啟用我們的規則。
// ... 其他 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>
標簽里嘗試寫下:
import { someFunction } from '@/services/api';
你會立刻看到,這行代碼被畫上了紅色波浪線,當你把鼠標懸停在上面時,會顯示我們自定義的錯誤信息:“頁面組件不允許直接導入 service,請通過狀態管理層調用。”
而在 src/utils
或其他非 pages
目錄的文件中進行同樣的導入,則不會有任何報錯。
就這樣成功地創建并應用了一條非常有價值的、用于維護項目架構的自定義 ESLint 規則!