9.0 KiB
9.0 KiB
路径别名使用指南
📁 已配置的路径别名
项目已为所有核心目录配置了路径别名,让您的导入语句更简洁、更清晰。
完整别名列表
| 别名 | 实际路径 | 用途 |
|---|---|---|
@ |
./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 报错?
解决方案:
- 确保运行了
pnpm install - 重启 VSCode 或 IDE
- 检查
tsconfig.json和vite.config.ts配置是否正确 - 运行
pnpm dev启动开发服务器
Q2: ESLint 提示找不到模块?
解决方案:
- 确保
.eslintrc-auto-import.json文件已生成 - 检查
.eslintrc.cjs中的路径别名配置 - 运行
pnpm lint检查配置
Q3: SCSS 中使用别名报错?
解决方案:
在 SCSS 中使用别名时,确保使用 @use 或正确的 URL 格式:
// ✅ 正确
.logo {
background-image: url('@assets/images/logo.png');
}
// 或者使用波浪号
.logo {
background-image: url('~@assets/images/logo.png');
}
Q4: 类型提示不完整?
解决方案:
- 运行
pnpm type-check检查类型 - 确保
src/auto-imports.d.ts和src/components.d.ts已生成 - 重启 TypeScript 服务(VSCode:
Ctrl+Shift+P→TypeScript: Restart TS Server)
📚 总结
路径别名的优势:
- ✅ 代码更简洁、可读性更强
- ✅ 重构时更容易维护
- ✅ 避免相对路径错误
- ✅ IDE 自动补全更准确
- ✅ 团队协作更统一
现在您可以在项目中愉快地使用路径别名了! 🎉