🔥Vite+ElementPlus 自动按需加载与主题定制原理全解析

第一步:安装插件

首先需要安装unplugin-vue-componentsunplugin-auto-import这两款插件

ts 复制代码
yarn add -D unplugin-vue-components unplugin-auto-import

第二步:配置vite.config.ts 按需加载插件

配置好插件,以及指定组件类型声明文件的路径。此后vite每次编译都会生成相应的组件类型文件。

配置完成之后,此时组件就可以自动按需引入了。

需要注意的是代码中不能从element-plus中导入组件,如果导入的话会导致组件样式丢失。

ts 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
 
export default defineConfig({
  plugins: [
      vue(),
      // 按需加载-自动导入
      Components({
        resolvers: [ElementPlusResolver()],
        dts: 'src/typings/components.d.ts' // 指定类型声明文件的路径
      }),
      AutoImport({
        resolvers: [ElementPlusResolver()],
        dts: 'src/typings/auto-imports.d.ts'
      }),
  ]
})

第三步:创建scss文件,配置主题

创建theme.scss,这个文件将用于覆盖 Element Plus 的默认样式变量。

使用 @forward 的作用是不要用原来的版本,请转发我这个版本,并用我传入的变量覆盖原变量,通过 with 关键字来覆盖它们。

也就是说你构建了一个新的「var 模块」,它依然暴露和 Element Plus 一样的变量名字,但值已经改成了你自己的主题色。

ts 复制代码
// element plus 主题配置

@forward 'element-plus/theme-chalk/src/common/var.scss' with (
  $colors: (
    'primary': (
      'base': #00ac7a
    )
  ),
  $border-color: (
    '': rgba(219, 223, 233, 0.6)
  )
);

第四步:vite scss文件编译配置

这个步骤保证了,在编译任何 scss 文件之前,先自动插入这一行。每个组件的 SCSS 文件在编译时都会包含你的自定义变量。

ts 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
 
export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      resolvers: [ElementPlusResolver({ importStyle: "sass" })],
    }),
    Components({
      resolvers: [ElementPlusResolver({ importStyle: "sass" })],
    }),
  ],
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `
          @use "@/styles/theme.scss" as *;
        `,
      },
    },
   },
})

element-plus 的 sass文件编译过程如下

rust 复制代码
vite -> 加载每个 scss 文件
     -> 先执行 @use "@/styles/theme.scss"
         ↳ @forward element-plus/theme-chalk/src/common/var.scss with ($colors ...自定义... )
     -> 编译 element-plus 源码中的 @use 'common/var' as *;
         ↳发现已经被覆盖 -> 使用新的值

vite配置中 ElementPlusResolver 中 importStyle 的作用

一、背景:Element Plus 的样式有两种版本

Element Plus 每个组件都有两套样式源码:

类型 路径 用途
CSS element-plus/theme-chalk/index.css 编译好的纯 CSS(不带变量)
SASS (SCSS) element-plus/theme-chalk/src/*.scss 源代码,包含变量与 mixin,可主题定制

当你使用自动按需导入插件 unplugin-vue-components 来加载组件时,插件需要知道:

当引入组件时,它应该加载 哪一套样式


二、importStyle 的作用

importStyle 控制 Element Plus Resolver 在自动导入组件时,应该引入哪种样式文件

取值说明:

说明 加载的文件
"css" 默认值,加载编译好的 CSS 文件 element-plus/theme-chalk/el-button.css
"sass" 加载源码中的 SCSS 文件 element-plus/theme-chalk/src/button.scss

三、为什么 "sass" 很重要

如果你写的是:

ts 复制代码
ElementPlusResolver({ importStyle: "css" })

则每个按需加载的组件都会导入处于最终态的 CSS 文件:

ts 复制代码
import "element-plus/theme-chalk/el-button.css";

这些文件已经被编译完成,不再包含 Sass 变量,也不会受你的主题配置影响。

但如果你写的是:

ts 复制代码
ElementPlusResolver({ importStyle: "sass" })

它会导入组件源码对应的 SCSS:

ts 复制代码
import "element-plus/theme-chalk/src/button.scss";

这些 SCSS 文件仍然保留了对变量模块的引用,例如:

ts 复制代码
@use 'common/var' as *;
.el-button {
  background-color: map.get($colors, 'primary', 'base');
}

👉 这就允许你的 Sass 主题重写变量(@forward)生效。

这也是你能通过 theme.scss 覆盖 Element Plus 主色的关键前提。

四、这段配置在执行时的整体逻辑

ts 复制代码
Components({
  resolvers: [ElementPlusResolver({ importStyle: "sass" })],
}),

执行过程:

  1. 解析你模板中的 <el-button>

  2. 自动生成引入语句:

    ts 复制代码
    import { ElButton } from "element-plus";
    import "element-plus/theme-chalk/src/button.scss";
  3. Vite 编译这份 SCSS 时,会应用全局注入配置:

    ts 复制代码
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: `@use "@/styles/theme.scss" as *;`
        },
      },
    },
  4. 因为组件样式导入了源码,它内部引用的变量 var.scss 会被自定义主题替换。

  5. 构建结果就是:组件颜色来自 $colors.primary.base = #00ac7a 而不是默认蓝色。

相关推荐
零一科技2 小时前
Vue3拓展:实现原理 - 浅析
前端·vue.js
抱琴_2 小时前
【Vue3】从混乱到有序:我用 1 个 Vue Hooks 搞定大屏项目所有定时任务
前端·vue.js
文心快码BaiduComate2 小时前
用文心快码写个「隐私优先」的本地会议助手
前端·后端·程序员
Cerrda2 小时前
Windows系统中使用fnm自动管理node版本
前端
胡琦博客2 小时前
21天开源鸿蒙训练营|Day2 ReactNative 开发 OpenHarmony 应用环境搭建实录
javascript·react native·react.js
samroom2 小时前
什么是MVVM以及HTML小案例
前端·html
mwq301232 小时前
《前端项目技术文档生成器》Prompt(可复用模板)
前端·llm·visual studio code
6***37942 小时前
React Native热更新方案
javascript·react native·react.js
x***J3482 小时前
React Native组件封装
javascript·react native·react.js