目前 element-plus 如果直接导入组件使用,组件是没有样式的。因为默认不会自动导入 CSS。需要依赖插件。
官方的插件是 unplugin-element-plus 。查看 仓库页面 可以找到针对不同框架的文档。
如果需要自己构建插件,这里提供一种方案。
/**
* Element Plus 样式按需注入插件
*
* 自动检测源码中使用的 Element Plus 组件,并注入对应的 CSS 样式导入。
* 通过扫描 node_modules/element-plus/es/components 目录建立组件名映射,
* 确保只注入真实存在的组件样式。
*/
import { readdir } from "node:fs/promises";
import { pascalCase } from "change-case";
import MagicString from "magic-string";
import type { Plugin } from "vite";
/** 组件名映射:PascalCase -> kebab-case(如 ElButton -> button) */
const componentMap = new Map<string, string>();
// 初始化时扫描 Element Plus 组件目录,建立有效组件白名单
const componentsDir = "node_modules/element-plus/es/components";
for (const dir of await readdir(componentsDir, { withFileTypes: true })) {
if (!dir.isDirectory()) continue;
componentMap.set(pascalCase(dir.name), dir.name);
}
/** 匹配 El 开头的组件标识符(如 ElButton、ElTable) */
const elComponentRE = /\bEl([A-Z][a-zA-Z0-9]*)\b/g;
/**
* Element Plus 样式自动注入插件
*
* 在 transform 阶段检测源码中使用的 Element Plus 组件,
* 自动追加对应的 CSS 样式导入语句。
*/
export const elementPlusPlugin: Plugin = {
name: "element-plus-style",
enforce: "post",
transform(code, id) {
// 跳过 node_modules 中的文件
if (id.includes("node_modules")) return null;
// 只处理 .ts 文件和 Vue SFC 的 script 块
if (!id.endsWith(".ts") && !id.includes("?vue&type=script")) return null;
if (!code) return null;
// 收集源码中使用的有效组件名
const components = new Set<string>();
for (const match of code.matchAll(elComponentRE)) {
const [, name] = match;
if (!componentMap.has(name)) continue;
components.add(name);
}
if (components.size === 0) return null;
// 生成样式导入语句
const styleImports = [...components]
.map((c) => `import 'element-plus/es/components/${componentMap.get(c)}/style/css'`)
.join("\n");
// 使用 magic-string 追加导入语句并生成 source map
const s = new MagicString(code);
s.append("\n" + styleImports);
return {
code: s.toString(),
map: s.generateMap({ source: id, includeContent: true }),
};
},
};
直接在 vite.config.ts 中导入使用即可。至于性能如何,可自行测试。