创建vue项目的不同方式
pnpm create vite 使用于创建一些组件库,第三方库的时候
pnpm create vue 适用于vue项目,内部有一些基础的样式,vue的主题,
element-plus主题配置
按需引入element
1. scss变量自定义主题
分支:feature-element-theme-anxu-scss
src/styles/element/index.scss
less
/* just override what you need */
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
$colors: (
'primary': (
'base': green,
),
)
);
vite.config.ts
php
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import ElementPlus from 'unplugin-element-plus/vite'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [
ElementPlusResolver({
importStyle: 'sass',
}),
],
}),
ElementPlus({
useSource: true,
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "@/styles/element/index.scss" as *;`,
},
},
},
})
按需引入组件时,使用组件,会自动引入对应组件的样式,不用再main.ts中引入elememnt的全部样式。
主题配置只需要修改需要改变的颜色变量即可
可以看到,对应组件的颜色变量已经变化

2. css变量自定义主题
分支: feature-element-theme-anxu-css
src/styles/element/index.scss
css
:root {
--el-color-primary: green;
}
vite.config.ts
php
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import ElementPlus from 'unplugin-element-plus/vite'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [
ElementPlusResolver({
importStyle: 'sass',
}),
],
}),
ElementPlus({
useSource: true,
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "@/styles/element/index.scss" as *;`,
},
},
},
})
可以看到,css变量被注入到组件对应的scss文件顶部,从而让主题生效

全量引入element
scss全量引入
分支 feature-element-theme-all-scss
less
/* just override what you need */
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
$colors: (
'primary': (
'base': green,
),
)
);
// If you just import on demand, you can ignore the following content.
// 如果你是全量导入,需要加下边这句,如果是按需引入,请注释掉下边这句
@use 'element-plus/theme-chalk/src/index.scss' as *;
main.ts
javascript
import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import './styles/element/index.scss'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(ElementPlus)
app.mount('#app')
这时候可以看到样式被全部引入了

css全量引入
分支:feature-element-theme-all-css src/styles/element/index.css
css
:root {
--el-color-primary: green;
}
main.ts
javascript
import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import './styles/element/index.css'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(ElementPlus)
app.mount('#app')
可以看到,element的css变量已经被覆盖了

动态主题
运行时动态切换主题,不能依赖scss变量
原因
SCSS 变量是编译时变量,在构建阶段就被替换掉了,在浏览器运行时无法再改变,所以无法用于"动态切换主题"。
动态主题应该使用css变量来实现
官方提供了一个切换主题的项目github.com/element-plu...
里面引入了一套暗黑模式的样式,然后通过 useToggle进行切换
分支 feature-element-theme-anxu-scss-dynamic 还是采用按需引入elememnt的方式
src/styles/index.scss 这里全量引入暗黑模式的样式
css
// import dark theme
@use 'element-plus/theme-chalk/src/dark/css-vars.scss' as *;
// :root {
// --ep-color-primary: red;
// }
body {
font-family:
Inter, system-ui, Avenir, 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB',
'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
margin: 0;
}
a {
color: var(--ep-color-primary);
}
main.ts在main.ts中引入样式
javascript
// import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import '@/styles/index.scss'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')
src/styles/element/index.scss 这里是自定义默认主题变量
perl
$--colors: (
'primary': (
'base': rgb(0, 128, 19),
),
'success': (
'base': #21ba45,
),
'warning': (
'base': #f2711c,
),
'danger': (
'base': #db2828,
),
'error': (
'base': #db2828,
),
'info': (
'base': #42b8dd,
),
);
// You should use them in scss, because we calculate it by sass.
// comment next lines to use default color
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
// do not use same name, it will override.
$colors: $--colors // $button-padding-horizontal: ('default': 50px)
);
// if you want to import all
// @use "element-plus/theme-chalk/src/index.scss" as *;
// You can comment it to hide debug info.
// @debug $--colors;
// custom dark variables
@use './dark.scss';
src/styles/element/dark.scss 这是对暗黑主题颜色重新定义
css
// only scss variables
$--colors: (
'primary': (
'base': #589ef8,
),
);
@forward 'element-plus/theme-chalk/src/dark/var.scss' with (
$colors: $--colors
);
vite.config.ts 这里引入自定义主题变量,自定义默认主题和暗黑主题颜色
php
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import ElementPlus from 'unplugin-element-plus/vite'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [
ElementPlusResolver({
importStyle: 'sass',
}),
],
}),
ElementPlus({
useSource: true,
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "@/styles/element/index.scss" as *;`,
},
},
},
})
动态切换主题
- 通过useDark获取当前是否是暗黑模式
- 通过useToggle切换主题
xml
<script setup lang="ts">
import { RouterLink, RouterView } from 'vue-router'
import { useDark, useToggle } from '@vueuse/core'
const isDark = useDark()
const toggleDark = useToggle(isDark)
const changeTheme = () => {
toggleDark()
}
</script>
<template>
<header>
<el-button type="primary" @click="changeTheme"> 切换主题 </el-button>
<el-input></el-input>
</header>
<RouterView />
</template>
<style scoped>
header {
line-height: 1.5;
max-height: 100vh;
}
.logo {
display: block;
margin: 0 auto 2rem;
}
nav {
width: 100%;
font-size: 12px;
text-align: center;
margin-top: 2rem;
}
nav a.router-link-exact-active {
color: var(--color-text);
}
nav a.router-link-exact-active:hover {
background-color: transparent;
}
nav a {
display: inline-block;
padding: 0 1rem;
border-left: 1px solid var(--color-border);
}
nav a:first-of-type {
border: 0;
}
@media (min-width: 1024px) {
header {
display: flex;
place-items: center;
padding-right: calc(var(--section-gap) / 2);
}
.logo {
margin: 0 2rem 0 0;
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
nav {
text-align: left;
margin-left: -1rem;
font-size: 1rem;
padding: 1rem 0;
margin-top: 1rem;
}
}
</style>
代码仓库地址 github.com/Stacey1018/...