开发优化:vue-component 的自动导入指令
概述
本节扩展 unplugin-vue-components 的 resolver,使其支持自定义指令的自动导入。参照 Element Plus 的 directive resolver 实现,为组件库中的指令提供按需加载能力。
Element Plus Directive Resolver 分析
实现原理
Element Plus 在 resolver 中同时处理组件和指令的自动导入:
// Element Plus resolver 核心结构
const directives: Record<string, string[]> = {
Loading: ['loading'],
InfiniteScroll: ['infinite-scroll'],
// ...
}
export function ElementPlusResolver(options): ComponentResolver[] {
return [
{
type: 'component',
resolve: (name) => { /* 组件解析 */ },
},
{
type: 'directive',
resolve: (name) => {
// 判断传入的名称是否在 directives 映射中
const directive = directives[name]
if (directive) {
return {
name: directive[0],
from: 'element-plus',
sideEffects: [], // 加载对应样式
}
}
},
},
]
}
typescript
关键区别
| 特征 | 组件 Resolver | 指令 Resolver |
|---|---|---|
| type | 'component' | 'directive' |
| 注册方式 | 全局/局部注册组件 | app.directive() 注册 |
| 导出方式 | 单个组件导出 | 需从 directives/ 目录单独导出 |
自定义指令导出改造
问题
组件库的指令通过统一入口文件 install 方法批量注册,无法按需导入:
// 原始方式:统一注册(不支持按需)
export function setupDirectives(app: App) {
app.directive('copy', copyDirective)
app.directive('loading', loadingDirective)
// ...
}
typescript
解决方案
为每个指令创建单独的导出文件:
// directives/modules/copy.ts
export { default as VpCopy } from './copy'
// directives/modules/loading.ts
export { default as VpLoading } from './loading'
typescript
自动化脚本生成 Directive Resolver
// build/scripts/gen-directives.ts
const directivesDir = path.join(__dirname, '../src/directives/modules')
const directiveFiles = fs.readdirSync(directivesDir)
const resolverEntries = directiveFiles.map(file => {
const name = file.replace('.ts', '')
return {
name: `Vp${capitalize(name)}`, // VpCopy, VpLoading
importName: name, // copy, loading
from: pkgName,
}
})
// 输出 resolver 配置
const output = `
export const vpDirectiveResolve = ${JSON.stringify(resolverEntries, null, 2)}
.map(item => ({
type: 'directive' as const,
resolve: (name: string) => {
if (name === item.name) {
return { name: item.importName, from: '${pkgName}' }
}
}
}))
`
typescript
使用方式
// vite.config.ts
import { vpDirectiveResolve } from '@el-admin/components/vite-config'
Components({
resolvers: [
vpDirectiveResolve,
// 需要在头部 import usingRoot
],
directives: true,
})
typescript
错误处理
当 resolver 找不到对应指令时,返回默认值避免报错:
resolve: (name: string) => {
if (name === 'VpCopy') {
return { name: 'copy', from: pkgName }
}
// 不匹配时返回 undefined(默认行为)
return undefined
}
typescript
关键要点
unplugin-vue-components支持type: 'directive'的 resolver,用于指令自动导入- 需将指令从统一入口改为单独导出,支持按需加载
- 自动化脚本遍历
directives/modules/目录生成 resolver 映射 - Resolver 需处理不匹配的情况,返回
undefined避免运行时错误
↑