Element Plus 自动导入 CSS 样式

目前 element-plus 如果直接导入组件使用,组件是没有样式的。因为默认不会自动导入 CSS。需要依赖插件。

官方的插件是 unplugin-element-plus 。查看 仓库页面 可以找到针对不同框架的文档。

如果需要自己构建插件,这里提供一种方案。

typescript 复制代码
/**
 * 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 中导入使用即可。至于性能如何,可自行测试。

相关推荐
java1234_小锋15 小时前
Vue3专题 - 组件基础
vue.js·vite
阿懂在掘金20 小时前
同一份弹窗我重构了三次:从 v-model 地狱到路由式调用,终于治好了模板臃肿
前端·vue.js·前端框架
小锋java12341 天前
【技术专题】Vue3 - 生命周期
vue.js·vite
Highcharts.js1 天前
Vue 3 + Highcharts Boost 可视化加速模块的完整示例
javascript·vue.js·可视化·boost·highcharts·图表渲染·加速模块
夏幻灵1 天前
从语法坑点到 JS 内存底层:Vue 3 watch 侦听器深度全解
开发语言·javascript·vue.js
Sterting1 天前
反馈组件:对话框、消息与通知
前端·javascript·vue.js
书中枫叶1 天前
做了个「句拾」小程序,最难的不是业务,是字体
前端·javascript·vue.js
新时代牛马1 天前
Vue.js 响应式原理详解
前端·javascript·vue.js
满栀5851 天前
vue3动态路由详细效果
前端·javascript·vue.js·typescript·前端框架
山荷枝1 天前
05-Vue
前端·javascript·vue.js