实现vue-element-admin换肤功能一般分为以下几个步骤:
- 安装依赖
npm install --save-dev style-resources-loader
- 配置less变量及全局样式
在src/styles/variables.scss
中定义仪表盘样式,如下:
@import '~element-theme-chalk/src/index'; // 引入所有 less 变量
// Dashboard Theme
$--color-primary: #13ce66;
$--color-success: #13ce66;
$--color-warning: #f7ba2a;
$--color-error: #ff4949;
$--color-breadcrumb: #c4c4cc;
// navmenu active color
$--color-nav-menu-active-text: #13ce66;
$--color-nav-menu-active-bg: #e4f7ff;
// css overrides
$--color-body-background-color: #f5f6fa;
$--color-scrollbar-background-color: '#eff2f6';
$--color-scrollbar-thumb-background-color: '#c5c8ce';
$--color-scrollbar-hover-thumb-background-color: '#a2a6ad';
// App Layout variables overrides
$--header-height: 60px;
$--menu-text-color: #57627B;
$--menu-text-color-active: #13ce66;
$--menu-background-color: #fff;
$--menu-width: 260px;
$--menu-collapse-width: 80px;
$--menu-item-height: 42px;
// overwrite font family after loading fonts
$--font-family: 'Noto Sans SC', 'sans-serif';
然后在src/styles/index.scss
中引入上述变量,并通过vue.config.js
配置文件全局注入样式:
@import './variables.scss';
// add global css
* {
margin: 0;
padding: 0;
}
.app-container {
width: 100%;
height: 100%;
}
.wf-sans-serif {
font-family: 'Noto Sans SC', 'sans-serif' !important;
}
.shopville-header {
height: $--header-height;
background-color: $--color-primary;
color: #fff;
display: flex;
justify-content: space-between;
align-items: center;
.logo {
width: 100px;
height: $--header-height;
display: flex;
align-items: center;
padding-left: 24px;
img {
width: 100%;
}
}
.userinfo {
display: flex;
align-items: center;
}
.avatar {
width: 36px;
height: 36px;
margin-right: 8px;
cursor: pointer;
img {
width: 100%;
}
}
.username {
font-size: 14px;
font-weight: 600;
}
}
@media (max-width: 768px) {
.shopville-header {
.userinfo {
display: none;
}
}
}
// override element-ui css
.el-dropdown-menu__item {
font-size: 14px;
}
.el-dropdown-menu__item-group.title {
font-size: 14px;
padding: 12px 12px 8px 12px !important;
}
.el-menu::after,
.el-submenu::after {
border-bottom: none;
}
.el-menu {
width: $--menu-width;
text-align: center;
background-color: $--menu-background-color !important;
.el-menu-item {
height: $--menu-item-height;
line-height: $--menu-item-height;
font-size: 14px;
color: $--menu-text-color;
}
.el-menu-item:hover {
background-color: $--menu-collapse-background-color !important;
color: $--menu-text-color-active !important;
}
.el-menu-item.is-active {
color: $--menu-text-color-active !important;
font-weight: bold;
background-color: $--menu-collapse-background-color !important;
}
.el-submenu__title {
line-height: $--menu-item-height;
font-size: 14px;
color: $--menu-text-color;
}
}
.el-menu--collapse {
width: $--menu-collapse-width;
.el-menu-item {
line-height: $--menu-item-height;
font-size: 14px;
margin: 0 auto;
}
.el-menu-item:hover {
background-color: $--menu-collapse-background-color !important;
}
.el-menu-item.is-active,
.el-menu-item:hover {
background-color: $--menu-collapse-background-color !important;
color: $--menu-text-color-active !important;
}
.el-submenu__title {
line-height: $--menu-item-height;
font-size: 14px;
margin: 0 auto;
}
}
配置vue.config.js
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
lintOnSave: false,
// 配置全局 less 变量
css: {
loaderOptions: {
less: {
prependData: `
@import "@/styles/variables.scss";
@import "@/styles/mixins.scss";
`
}
}
},
chainWebpack: config => {
config.resolve.alias
.set('@$', resolve('src'))
.set('@api', resolve('src/api'))
.set('@assets', resolve('src/assets'))
.set('@comp', resolve('src/components'))
.set('@layouts', resolve('src/layouts'))
.set('@router', resolve('src/router'))
.set('@store', resolve('src/store'))
.set('@views', resolve('src/views'))
.set('@utils', resolve('src/utils'))
},
pluginOptions: {
'style-resources-loader': {
preProcessor: 'less',
patterns: [path.resolve(__dirname, './src/styles/variables.scss')]
}
}
}
- 自定义换肤
|-- public
|-- src
| |-- styles
| |-- index.scss
| |-- variables.scss
| |-- components
| |-- ThemePicker.vue
|-- vue.config.js
在src/components
目录下新建ThemePicker.vue
组件:
<template>
<color-picker
v-model="color"
format="hex"
disabled-alpha
size="small"
color-format-input
popper-append-to-body
@change="handleChangeColor"
>
<div class="color-picker-btn">
<span class="color-picker-btn-color" :style="{ backgroundColor: color }"></span>
</div>
</color-picker>
</template>
<script>
import { ColorPicker } from 'element-ui'
export default {
components: {
ColorPicker
},
data() {
return {
color: ''
}
},
mounted() {
this.color = this.getThemeColor()
},
methods: {
getThemeColor() {
return localStorage.getItem('themeColor') || '#13ce66'
},
setThemeColor(color) {
localStorage.setItem('themeColor', color)
window.$eventBus.$emit('themeChange')
},
handleChangeColor() {
this.setThemeColor(this.color)
}
}
}
</script>
<style scoped>
.color-picker-btn {
display: flex;
justify-content: center;
align-items: center;
width: 24px;
height: 24px;
.color-picker-btn-color {
display: block;
width: 100%;
height: 100%;
border-radius: 50%;
}
}
</style>
在src/App.vue
中加入自定义换肤标签:
<template>
<div class="app-container">
<div class="shopville-header">
<div class="logo">
<img src="@/assets/images/logo.png" />
</div>
<div class="userinfo">
<theme-picker />
<a-dropdown>
<a-avatar class="avatar" icon="user">
<img
slot="avatar"
src="https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png"
alt=""
/>
</a-avatar>
<a-menu slot="overlay">
<a-menu-item>
<a-icon :type="$route.meta.icon" />
<span>我的工作台</span>
</a-menu-item>
<a-menu-divider />
<a-menu-item>
<a-icon type="logout" />
<span>退出登录</span>
</a-menu-item>
</a-menu>
</a-dropdown>
</div>
</div>
<app-main />
</div>
</template>
<script>
import ThemePicker from './components/ThemePicker.vue'
export default {
components: {
ThemePicker
},
created() {
this.changeThemeColor()
},
methods: {
changeThemeColor() {
const $primaryColor = localStorage.getItem('themeColor') || '#13ce66'
const cssText = `
:root {
--color-primary: ${$primaryColor};
--color-success: ${$primaryColor};
}
.el-table__body {
font-size: 14px;
}`
const styleEle = document.createElement('style')
styleEle.id = 'global_theme'
styleEle.innerText = cssText
document.head.append(styleEle)
}
}
}
</script>
示例说明1:
以element-theme-chalk
主题为例,我们可以在src/styles/variables.scss
文件中自定义 主题颜色和元素颜色。
@import '~element-theme-chalk/src/index'; // 引入所有 less 变量
// 定义主题色
$--color-primary: #13ce66;
$--color-success: #13ce66;
$--color-warning: #F7BA2A;
$--color-error: #FF4949;
// 定义元素颜色
$--color-breadcrumb: #c4c4cc;
示例说明2:
自定义换肤,我们可以在src/components/
目录下新建一个ThemePicker.vue
组件来选择自己喜欢的颜色。然后在src/App.vue
中使用此组件,并监听localStorage
的变化,在主题颜色改变时重新渲染页面。
<template>
<color-picker
v-model="color"
format="hex"
disabled-alpha
size="small"
color-format-input
popper-append-to-body
@change="handleChangeColor"
>
<div class="color-picker-btn">
<span class="color-picker-btn-color" :style="{ backgroundColor: color }"></span>
</div>
</color-picker>
</template>
<script>
import { ColorPicker } from 'element-ui'
export default {
components: {
ColorPicker
},
data() {
return {
color: ''
}
},
mounted() {
this.color = this.getThemeColor()
},
methods: {
getThemeColor() {
return localStorage.getItem('themeColor') || '#13ce66'
},
setThemeColor(color) {
localStorage.setItem('themeColor', color)
window.$eventBus.$emit('themeChange')
},
handleChangeColor() {
this.setThemeColor(this.color)
}
}
}
</script>
<style scoped>
.color-picker-btn {
display: flex;
justify-content: center;
align-items: center;
width: 24px;
height: 24px;
.color-picker-btn-color {
display: block;
width: 100%;
height: 100%;
border-radius: 50%;
}
}
</style>
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue-element换肤所有主题色和基础色均可实现自主配置 - Python技术站