Implemented functions
1. After switching the skin, the login page displays different background pictures, font colors, and the background color of the selected state.
2. The introduced elementUI component is also switched to the corresponding theme color.
3. Through the VUex state manager, store the currently selected theme properties (including background color, font color, selected state color, etc.). Can be configured according to different requirements). In any component, the subject property can be called through the Store. Also, the theme properties can be called directly from within the CSS file.
SwitchSkin component code for switching themes
<template> <! -- Theme Style selector --><div class="theme-picker">
<div
class="selected-theme webkit-transition"
:style="{ background: selectedColor || themeSelectedColor }"
>
<div class="logo">
<img src="static/img/theme/skin.png" alt="" />
</div>
<div class="text">Switch the skin</div>
</div>
<div
v-for="(item, index) in themeColorList"
:key="index"
class="theme-item"
@click="themeChange(item.color)"
>
<div class="bg" :style="{ background: item.color + '4d' }" />
<div class="color" :style="{ background: item.color }">
<img
v-show="item.color == selectedColor"
src="static/img/theme/check.png"
alt=""
/>
</div>
<div class="text">
{{ item.text }}
</div>
</div>
</div>
</template>
<script>
import { ThemeChangeMixin } from "@/mixins/ThemeChangeMixin";
export default {
name: "".components: {},
mixins: [ThemeChangeMixin],
props: {},
data() {
return {};
},
computed: {},
created() {},
mounted() {},
methods: {}}; </script><style lang="scss" scoped>
/* Theme style selection */
.theme-picker {
position: absolute;
right: 0;
width: 40px;
height: 40px;
top: 80px;
font-size: 14px;
border-radius: 7px 0 0 7px;
overflow: hidden;
-webkit-transition: all 1s ease 0.1 s;
-o-transition: all 1s ease 0.1 s;
-moz-transition: all 1s ease 0.1 s;
transition: all 1s ease 0.1 s;
&:hover {
width: 118px;
right: 0;
height: 120px;
.selected-theme {
.text {
display: block; }}}.selected-theme {
display: flex;
align-items: center;
height: 40px;
cursor: pointer;
.logo {
width: 16px;
height: 16px;
margin: 3px 9px 0 12px;
-webkit-animation: swing 3s;
-webkit-animation-iteration-count: 3;
-webkit-animation-delay: 3s;
}
.text {
display: none;
color: #fff;
width: 100%;
text-align: left; }}.theme-item {
display: flex;
align-items: center;
height: 40px;
border: 1px solid #e5e5e5;
background: #fff;
cursor: pointer;
&:hover {
// background: #e4e6f4 ! important;
.bg {
opacity: 1; }} &:last-child {
border: none;
}
.bg {
height: 40px;
width: 100%;
position: absolute;
opacity: 0;
}
.color {
width: 16px;
height: 16px;
margin: 0 9px 0 12px;
padding: 8px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
img {
width: 11px;
height: 10px;
display: block;
position: absolute;
left: 3px;
top: 3px; }}.text {
color: # 757575;
width: 100%;
text-align: left; }}}</style>
Copy the code
Css3 property gradient
Over the selector, the theme selection drop-down box expands. Use cSS3-webkit-Transition to create a soft gradient.
.theme-picker {
position: absolute;
right: 0;
width: 40px;
height: 40px;
top: 80px;
font-size: 14px;
border-radius: 7px 0 0 7px;
overflow: hidden;
-webkit-transition: all 1s ease 0.1 s;
-o-transition: all 1s ease 0.1 s;
-moz-transition: all 1s ease 0.1 s;
transition: all 1s ease 0.1 s;
&:hover {
width: 118px;
right: 0;
height: 120px;
.selected-theme {
.text {
display: block; }}}}Copy the code
“Mixin” files
import { ThemeChangeMixin } from "@/mixins/ThemeChangeMixin";
export default {
name: "".components: {},
mixins: [ThemeChangeMixin],
props: {},
data() {
return {};
},
computed: {},
created() {},
mounted() {},
methods: {}};Copy the code
The data for the theme skin, and how to switch themes, is in the ThemeChangeMixin file. As a mixin object, used in components that switch themes.
The mixin website has a detailed explanation
Cn.vuejs.org/v2/guide/mi…
The themeColorList array of topic options
themeColorList: [
{
color: '#3E50B3'.text: 'blue'.skin: {
themeImg: 'blue'.themeBgColor: '#D7DBEA'.themeNavColor: '#6573C4'.botColor: 'white'}}, {color: '#CD2E18'.text: 'red'.skin: {
themeImg: 'red'.themeBgColor: '#FAEAE8'.themeNavColor: '#DA523E'.botColor: 'black'}}]Copy the code
Vuex state manager, switch topics
The way to switch themes is as follows. After switching themes, change the current theme state through the state manager Vuex.
/* Switch the theme */
themeChange(val) {
if (this.selectedColor == val) return
this.selectedColor = val
this.$store.dispatch('settings/changeSetting', {
key: 'theme'.value: val
})
const list = this.themeColorList
const idx = list.findIndex((item) = > item.color == val)
Object.keys(list[0] ['skin']).forEach((item) = > {
const value = list[idx]['skin'][item]
this.$store.dispatch('settings/changeSetting', {
key: item,
value
})
})
this.changeElementTheme(val)
},
Copy the code
Settings. Js in the Modules store folder of Vuex configures the subjects-related state, mutations and Actions objects.
I have a very detailed article on the VUEX configuration.
const state = {
theme: '#3E50B3'.themeBgColor: '#D7DBE'.themeNavColor: '#6573C4'.themeImg: 'blue'.botColor: 'white'.websiteName: "".// System name
copyright: "".companyLogo: "",}const mutations = {
CHANGE_SETTING: (state, { key, value }) = > {
// eslint-disable-next-line no-prototype-builtins
if (state.hasOwnProperty(key)) {
state[key] = value
}
}
}
const actions = {
changeSetting({ commit }, data) {
commit('CHANGE_SETTING', data)
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
Copy the code
Switch to the elementUI theme
In the changeElementTheme method, load the different elementUI theme color files.
ThemeChangeMixin. Js file
/** Toggle skins and change the theme of mixin */
const version = require('element-ui/package.json').version // element-ui version from node_modules
const ORIGINAL_THEME = '#409EFF' // de
export const ThemeChangeMixin = {
data() {
return {
chalk: ' '.// content of theme-chalk css
selectedColor: ' '.themeSelectedColor: this.$store.state.settings.theme,
themeColorList: [{color: '#3E50B3'.text: 'blue'.skin: {
themeImg: 'blue'.themeBgColor: '#D7DBEA'.themeNavColor: '#6573C4'.botColor: 'white'}}, {color: '#CD2E18'.text: 'red'.skin: {
themeImg: 'red'.themeBgColor: '#FAEAE8'.themeNavColor: '#DA523E'.botColor: 'black'}}]}},created() {
this.selectedColor = this.themeSelectedColor
},
methods: {
/* Switch the theme */
themeChange(val) {
if (this.selectedColor == val) return
this.selectedColor = val
this.$store.dispatch('settings/changeSetting', {
key: 'theme'.value: val
})
const list = this.themeColorList
const idx = list.findIndex((item) = > item.color == val)
Object.keys(list[0] ['skin']).forEach((item) = > {
const value = list[idx]['skin'][item]
this.$store.dispatch('settings/changeSetting', {
key: item,
value
})
})
this.changeElementTheme(val)
},
async changeElementTheme(val) {
const oldVal = this.chalk ? this.themeSelectedColor : ORIGINAL_THEME
if (typeofval ! = ='string') return
const themeCluster = this.getThemeCluster(val.replace(The '#'.' '))
const originalCluster = this.getThemeCluster(oldVal.replace(The '#'.' '))
const getHandler = (variable, id) = > {
return () = > {
const originalCluster = this.getThemeCluster(
ORIGINAL_THEME.replace(The '#'.' '))const newStyle = this.updateStyle(
this[variable],
originalCluster,
themeCluster
)
let styleTag = document.getElementById(id)
if(! styleTag) { styleTag =document.createElement('style')
styleTag.setAttribute('id', id)
document.head.appendChild(styleTag)
}
styleTag.innerText = newStyle
}
}
if (!this.chalk) {
const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
await this.getCSSString(url, 'chalk')}const that = this
const chalkHandler = getHandler('chalk'.'chalk-style')
chalkHandler()
const styles = [].slice
.call(document.querySelectorAll('style'))
.filter((style) = > {
const text = style.innerText
return (
new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
)
})
styles.forEach((style) = > {
const { innerText } = style
if (typeofinnerText ! = ='string') return
style.innerText = this.updateStyle(
innerText,
originalCluster,
themeCluster
)
})
},
updateStyle(style, oldCluster, newCluster) {
let newStyle = style
oldCluster.forEach((color, index) = > {
newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
})
return newStyle
},
getCSSString(url, variable) {
return new Promise((resolve) = > {
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () = > {
if (xhr.readyState === 4 && xhr.status === 200) {
this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/.' ')
resolve()
}
}
xhr.open('GET', url)
xhr.send()
})
},
getThemeCluster(theme) {
const tintColor = (color, tint) = > {
let red = parseInt(color.slice(0.2), 16)
let green = parseInt(color.slice(2.4), 16)
let blue = parseInt(color.slice(4.6), 16)
if (tint === 0) {
// when primary color is in its rgb space
return [red, green, blue].join(', ')}else {
red += Math.round(tint * (255 - red))
green += Math.round(tint * (255 - green))
blue += Math.round(tint * (255 - blue))
red = red.toString(16)
green = green.toString(16)
blue = blue.toString(16)
return ` #${red}${green}${blue}`}}const shadeColor = (color, shade) = > {
let red = parseInt(color.slice(0.2), 16)
let green = parseInt(color.slice(2.4), 16)
let blue = parseInt(color.slice(4.6), 16)
red = Math.round((1 - shade) * red)
green = Math.round((1 - shade) * green)
blue = Math.round((1 - shade) * blue)
red = red.toString(16)
green = green.toString(16)
blue = blue.toString(16)
return ` #${red}${green}${blue}`
}
const clusters = [theme]
for (let i = 0; i <= 9; i++) {
clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
}
clusters.push(shadeColor(theme, 0.1))
return clusters
}
}
}
Copy the code
CSS var () function
Above, change the theme color through JS. So, can I use the theme color directly in the CSS file? The answer is yes, with the CSS var() function.
I introduced the theme colors in the app.vue file as follows, including the background color, the theme image, the bottom color, and so on. It can be configured according to specific requirements.
<template>
<div
id="app"
:style="{ '--themeColor': theme, '--themeBgColor': themeBgColor, '--themeNavColor': themeNavColor, '--themeImg': themeImg, '--botColor': botColor, }"
>
<router-view />
</div>
</template>
Copy the code
This property can then be called from within the CSS file via the CSS var function
.name{&:hover {
color: var(--themeColor);
transform: scale(1.1); }}Copy the code
App.vue complete code
<template>
<div
id="app"
:style="{ '--themeColor': theme, '--themeBgColor': themeBgColor, '--themeNavColor': themeNavColor, '--themeImg': themeImg, '--botColor': botColor, }"
>
<router-view />
</div>
</template>
<script>
import { ThemeChangeMixin } from '@/mixins/ThemeChangeMixin'
const version = require('element-ui/package.json').version // element-ui version from node_modules
const ORIGINAL_THEME = '#409EFF' // de
export default {
name: 'App'.mixins: [ThemeChangeMixin],
computed: {
theme() {
return this.$store.state.settings.theme
},
themeBgColor(){
return this.$store.state.settings.themeBgColor
},
themeNavColor(){
return this.$store.state.settings.themeNavColor
},
themeImg() {
return this.$store.state.settings.themeImg
},
botColor() {
return this.$store.state.settings.botColor
}
},
mounted() {
this.handleUserTheme()
},
methods: {
async handleUserTheme() {
const val = this.theme
const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
if (typeofval ! = ='string') return
const themeCluster = this.getThemeCluster(val.replace(The '#'.' '))
const originalCluster = this.getThemeCluster(oldVal.replace(The '#'.' '))
const getHandler = (variable, id) = > {
return () = > {
const originalCluster = this.getThemeCluster(
ORIGINAL_THEME.replace(The '#'.' '))const newStyle = this.updateStyle(
this[variable],
originalCluster,
themeCluster
)
let styleTag = document.getElementById(id)
if(! styleTag) { styleTag =document.createElement('style')
styleTag.setAttribute('id', id)
document.head.appendChild(styleTag)
}
styleTag.innerText = newStyle
}
}
if (!this.chalk) {
const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
await this.getCSSString(url, 'chalk')}const that = this
const chalkHandler = getHandler('chalk'.'chalk-style')
chalkHandler()
const styles = [].slice
.call(document.querySelectorAll('style'))
.filter((style) = > {
const text = style.innerText
return (
new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
)
})
styles.forEach((style) = > {
const { innerText } = style
if (typeofinnerText ! = ='string') return
style.innerText = this.updateStyle(
innerText,
originalCluster,
themeCluster
)
})
}
}
}
Copy the code