Files
CKB-Touchkebao/TouchVueThree/PATH_ALIAS_GUIDE.md
2026-01-12 11:57:00 +08:00

9.0 KiB
Raw Blame History

路径别名使用指南

📁 已配置的路径别名

项目已为所有核心目录配置了路径别名,让您的导入语句更简洁、更清晰。

完整别名列表

别名 实际路径 用途
@ ./src 根目录
@api ./src/api API 接口
@components ./src/components 公共组件
@composables ./src/composables 组合式函数
@stores ./src/stores Pinia Store
@utils ./src/utils 工具函数
@types ./src/types TypeScript 类型
@views ./src/views 页面组件
@assets ./src/assets 静态资源
@layouts ./src/layouts 布局组件
@directives ./src/directives 自定义指令

使用示例

不推荐:相对路径

// 深层嵌套,难以维护
import { useUserStore } from '../../../../stores/modules/user'
import ChatWindow from '../../../components/business/ChatWindow/index.vue'
import { formatDate } from '../../../utils/date'

推荐:路径别名

// 清晰明了,易于维护
import { useUserStore } from '@stores/modules/user'
import ChatWindow from '@components/business/ChatWindow/index.vue'
import { formatDate } from '@utils/date'

🎯 实际应用场景

1. 在 Vue 组件中使用

<script setup lang="ts">
// API 调用
import { getUserInfoApi } from '@api/modules/user'

// Store
import { useUserStore } from '@stores/modules/user'
import { useWeChatMessagesStore } from '@stores/modules/wechat/messages'

// Composables
import { useAuth } from '@composables/core/useAuth'
import { useMessages } from '@composables/business/useMessages'

// 组件
import ChatWindow from '@components/business/ChatWindow/index.vue'
import Loading from '@components/common/Loading/index.vue'

// 工具函数
import { formatDate } from '@utils/date'
import { isValidPhone } from '@utils/validator'

// 类型
import type { User } from '@types/user'
import type { ChatMessage } from '@types/wechat'

// 资源
import logo from '@assets/images/logo.png'
</script>

2. 在 TypeScript 文件中使用

// src/composables/business/useChat.ts
import { ref } from 'vue'
import { useWeChatMessagesStore } from '@stores/modules/wechat/messages'
import { sendMessageApi } from '@api/modules/wechat'
import { formatTimestamp } from '@utils/date'
import type { ChatMessage } from '@types/wechat'

export function useChat() {
  const messagesStore = useWeChatMessagesStore()
  const loading = ref(false)

  const sendMessage = async (content: string) => {
    loading.value = true
    try {
      await sendMessageApi({ content })
    } finally {
      loading.value = false
    }
  }

  return { sendMessage, loading }
}

3. 在 Store 中使用

// src/stores/modules/user.ts
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { loginApi, getUserInfoApi } from '@api/modules/user'
import { setToken, getToken } from '@utils/storage'
import type { User, LoginParams } from '@types/user'

export const useUserStore = defineStore('user', () => {
  const user = ref<User | null>(null)
  const token = ref(getToken())

  const login = async (params: LoginParams) => {
    const result = await loginApi(params)
    token.value = result.token
    user.value = result.user
    setToken(result.token)
  }

  return { user, token, login }
})

4. 在路由配置中使用

// src/router/routes.ts
import type { RouteRecordRaw } from 'vue-router'
import DefaultLayout from '@layouts/DefaultLayout.vue'
import ChatLayout from '@layouts/ChatLayout.vue'

export const routes: RouteRecordRaw[] = [
  {
    path: '/login',
    component: () => import('@views/Login/index.vue'),
  },
  {
    path: '/chat',
    component: ChatLayout,
    children: [
      {
        path: '',
        component: () => import('@views/Chat/index.vue'),
      },
    ],
  },
  {
    path: '/dashboard',
    component: DefaultLayout,
    children: [
      {
        path: '',
        component: () => import('@views/Dashboard/index.vue'),
      },
    ],
  },
]

5. 在 SCSS 中使用

<style scoped lang="scss">
// SCSS 中使用 @ 别名访问资源
.logo {
  background-image: url('@assets/images/logo.png');
}

.icon {
  background-image: url('@assets/icons/user.svg');
}
</style>

🔧 配置说明

路径别名已在以下三个配置文件中同步配置:

1. vite.config.ts - Vite 构建工具

resolve: {
  alias: {
    '@': path.resolve(__dirname, './src'),
    '@api': path.resolve(__dirname, './src/api'),
    '@components': path.resolve(__dirname, './src/components'),
    '@composables': path.resolve(__dirname, './src/composables'),
    '@stores': path.resolve(__dirname, './src/stores'),
    '@utils': path.resolve(__dirname, './src/utils'),
    '@types': path.resolve(__dirname, './src/types'),
    '@views': path.resolve(__dirname, './src/views'),
    '@assets': path.resolve(__dirname, './src/assets'),
    '@layouts': path.resolve(__dirname, './src/layouts'),
    '@directives': path.resolve(__dirname, './src/directives'),
  },
}

2. tsconfig.json - TypeScript 配置

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@api/*": ["./src/api/*"],
      "@components/*": ["./src/components/*"],
      "@composables/*": ["./src/composables/*"],
      "@stores/*": ["./src/stores/*"],
      "@utils/*": ["./src/utils/*"],
      "@types/*": ["./src/types/*"],
      "@views/*": ["./src/views/*"],
      "@assets/*": ["./src/assets/*"],
      "@layouts/*": ["./src/layouts/*"],
      "@directives/*": ["./src/directives/*"]
    }
  }
}

3. .eslintrc.cjs - ESLint 配置

settings: {
  'import/resolver': {
    alias: {
      map: [
        ['@', path.resolve(__dirname, './src')],
        ['@api', path.resolve(__dirname, './src/api')],
        // ... 其他别名
      ],
    },
  },
}

💡 最佳实践

1. 优先使用更具体的别名

// ✅ 推荐:使用具体的别名
import { useUserStore } from '@stores/modules/user'
import ChatWindow from '@components/business/ChatWindow/index.vue'

// ⚠️ 可以但不推荐:使用通用别名
import { useUserStore } from '@/stores/modules/user'
import ChatWindow from '@/components/business/ChatWindow/index.vue'

原因

  • 更具体的别名能让代码意图更清晰
  • IDE 的自动补全会更准确
  • 重构时更容易全局搜索和替换

2. 保持导入语句的一致性

// ✅ 推荐:按类型分组导入
<script setup lang="ts">
// 1. Vue 核心(自动导入)
// 2. 第三方库
import { ElMessage } from 'element-plus'

// 3. Stores
import { useUserStore } from '@stores/modules/user'

// 4. Composables
import { useAuth } from '@composables/core/useAuth'

// 5. API
import { getUserInfoApi } from '@api/modules/user'

// 6. 组件
import ChatWindow from '@components/business/ChatWindow/index.vue'

// 7. 工具函数
import { formatDate } from '@utils/date'

// 8. 类型
import type { User } from '@types/user'

// 9. 资源
import logo from '@assets/images/logo.png'
</script>

3. 类型导入使用 type 关键字

// ✅ 推荐:显式使用 type
import type { User } from '@types/user'
import type { ChatMessage } from '@types/wechat'

// ❌ 不推荐:混合导入
import { User, ChatMessage } from '@types/user'

4. 动态导入也可使用别名

// 路由懒加载
const routes = [
  {
    path: '/chat',
    component: () => import('@views/Chat/index.vue'),
  },
  {
    path: '/dashboard',
    component: () => import('@views/Dashboard/index.vue'),
  },
]

// 动态组件加载
const AsyncComponent = defineAsyncComponent(() =>
  import('@components/business/ChatWindow/index.vue')
)

🐛 常见问题

Q1: 路径别名不生效IDE 报错?

解决方案

  1. 确保运行了 pnpm install
  2. 重启 VSCode 或 IDE
  3. 检查 tsconfig.jsonvite.config.ts 配置是否正确
  4. 运行 pnpm dev 启动开发服务器

Q2: ESLint 提示找不到模块?

解决方案

  1. 确保 .eslintrc-auto-import.json 文件已生成
  2. 检查 .eslintrc.cjs 中的路径别名配置
  3. 运行 pnpm lint 检查配置

Q3: SCSS 中使用别名报错?

解决方案 在 SCSS 中使用别名时,确保使用 @use 或正确的 URL 格式:

// ✅ 正确
.logo {
  background-image: url('@assets/images/logo.png');
}

// 或者使用波浪号
.logo {
  background-image: url('~@assets/images/logo.png');
}

Q4: 类型提示不完整?

解决方案

  1. 运行 pnpm type-check 检查类型
  2. 确保 src/auto-imports.d.tssrc/components.d.ts 已生成
  3. 重启 TypeScript 服务VSCode: Ctrl+Shift+PTypeScript: Restart TS Server

📚 总结

路径别名的优势:

  • 代码更简洁、可读性更强
  • 重构时更容易维护
  • 避免相对路径错误
  • IDE 自动补全更准确
  • 团队协作更统一

现在您可以在项目中愉快地使用路径别名了! 🎉