Preface
Recently basedElementUI
The dynamic skinning function is required on the project, and here are two methods:
-
vue-element-admin
Official implementation method -
webpack-theme-color-replacer
How to implement plug-in
vue-element-admin official implementation method
Let me briefly explain its principle: After element-ui 2.0, all styles are written based on SCSS, and all colors are set based on several basic color variables, so it is not difficult to achieve dynamic skinning. Just find those color variables and modify it. First of all, we need to get the version number of element-ui through it, and request the corresponding style based on this version number. After getting the style, replace the color variable with what you need through regular matching and replacement, and then dynamically add the style tag to overwrite the original css style.
1. There is no brain reference herevue-element-admin
Source code, nowstyles
Create a folder namedFile, and in
This file is introduced in .
/* src/styles/ */ /* Change the theme color variable */ $--color-primary: #256DCB; $--color-success: #7AC800; $--color-danger: #EC4242; $--color-info: #999999; /* Change icon font path variable, required */ $--font-path: '~element-ui/lib/theme-chalk/fonts'; @import "~element-ui/packages/theme-chalk/src/index"; /* If the exported variable value is undefined, the file name needs to be changed to */ :export { theme: $--color-primary }
/* */ import Vue from 'vue' import Element from 'element-ui' import './' (Element)
2. It can be achieved through the above methodsElementUI
The theme has been replaced, but it is not enough to customize the color. Considering that the theme color is applied throughout the project, we save it toVuex
The next thing to do isstore/modules
Newly built 。
/* src/store/modules/ */ import variables from '@/styles/' import * as Types from '../mutation-types' const state = { theme: } const mutations = { CHANGE_SETTING: (state, { key, value }) => { ('theme', value) // Cache and reuse it when refreshing // eslint-disable-next-line no-prototype-builtins if ((key)) { state[key] = value } } } const actions = { changeSetting ({ commit }, data) { commit('CHANGE_SETTING', data) } } export default { namespaced: true, state, mutations, actions }
3. This step is also brainless copyvue-element-admin
The source code ofThemePicker
The code of the component, as follows:
/* src/components/ThemePicker/ */ <template> <el-color-picker v-model="theme" :predefine="['#256DCB', '#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', '#F80', ]" class="theme-picker" popper-class="theme-picker-dropdown" /> </template> <script> import { chalkCss } from './' // It is the css obtained from the getCSSString interface. Here I fixed the version number and cached the css locally. Remember to deal with the \ escape problem // const version = require('element-ui/').version // element-ui version from node_modules const ORIGINAL_THEME = '#409EFF' // primary color in default color, calculate a series of colors based on this color for regular replacement export default { name: 'ThemePicker', data () { return { chalk: '', // content of theme-chalk css theme: '' } }, computed: { defaultTheme () { return this.$ } }, watch: { defaultTheme: { handler: function (val, oldVal) { = val }, immediate: true }, async theme (val) { const oldVal = ? : ORIGINAL_THEME if (typeof val !== 'string') return const themeCluster = (('#', '')) const originalCluster = (('#', '')) (themeCluster, originalCluster) const $message = this.$message({ message: this.$t('theme_compiling'), customClass: 'theme-message', type: 'success', duration: 0, iconClass: 'el-icon-loading' }) const getHandler = (variable, id) => { return () => { const originalCluster = (ORIGINAL_THEME.replace('#', '')) const newStyle = (this[variable], originalCluster, themeCluster) let styleTag = (id) if (!styleTag) { styleTag = ('style') ('id', id) (styleTag) } = newStyle } } if (!) { // const url = `/element-ui@${version}/lib/theme-chalk/` // await (url, 'chalk') = (/@font-face{[^}]+}/, '') // Local cache, if you need to get online, use the above method. Advantages: no delay in switching, disadvantages: manual maintenance of css string } const chalkHandler = getHandler('chalk', 'chalk-style') chalkHandler() const styles = [].(('style')) .filter(style => { const text = return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text) }) (style => { const { innerText } = style if (typeof innerText !== 'string') return = (innerText, originalCluster, themeCluster) }) this.$emit('change', val) $() } }, methods: { updateStyle (style, oldCluster, newCluster) { let newStyle = style ((color, index) => { newStyle = (new RegExp(color, 'ig'), newCluster[index]) }) return newStyle }, getCSSString (url, variable) { return new Promise(resolve => { const xhr = new XMLHttpRequest() = () => { if ( === 4 && === 200) { this[variable] = (/@font-face{[^}]+}/, '') resolve() } } ('GET', url) () }) }, getThemeCluster (theme) { const tintColor = (color, tint) => { let red = parseInt((0, 2), 16) let green = parseInt((2, 4), 16) let blue = parseInt((4, 6), 16) if (tint === 0) { // when primary color is in its rgb space return [red, green, blue].join(',') } else { red += (tint * (255 - red)) green += (tint * (255 - green)) blue += (tint * (255 - blue)) red = (16) green = (16) blue = (16) return `#${red}${green}${blue}` } } const shadeColor = (color, shade) => { let red = parseInt((0, 2), 16) let green = parseInt((2, 4), 16) let blue = parseInt((4, 6), 16) red = ((1 - shade) * red) green = ((1 - shade) * green) blue = ((1 - shade) * blue) red = (16) green = (16) blue = (16) return `#${red}${green}${blue}` } const clusters = [theme] for (let i = 0; i <= 9; i++) { (tintColor(theme, Number((i / 10).toFixed(2)))) } (shadeColor(theme, 0.1)) return clusters } } } </script> <style> .theme-message, .theme-picker-dropdown { z-index: 99999 !important; } .theme-picker .el-color-picker__trigger { height: 26px !important; width: 26px !important; padding: 2px; } .theme-picker-dropdown .el-color-dropdown__link-btn { display: none; } </style>
4. Finally use it in the pageThemePicker
I'm putting the components hereheader
inside.
// template <theme-picker @change="themeChange" /> // js import ThemePicker from '@/components/ThemePicker' // methods themeChange (val) { this.$('settings/changeSetting', { key: 'theme', value: val }) }
So far, all dynamic skinning functions have been implemented, but there is another problem that the theme color will be reset after refreshing the page, so you need to cache the theme color tolocalStore
In order to refresh the theme color on any page, I choseAdded a page
ThemePicker
For components, see the following code for specific implementation:
/* src/ */ <template> <div :style="{'--color': defaultTheme}"> <theme-picker @change="themeChange" v-show="false" /> <router-view /> </div> </template> <script> import ThemePicker from '@/components/ThemePicker' export default { name: 'App', components: { ThemePicker }, computed: { defaultTheme () { return this.$ } }, mounted () { if (('theme')) { (('theme')) } }, methods: { themeChange (val) { this.$('settings/changeSetting', { key: 'theme', value: val }) } } } </script>
Other styles defined by yourself can use them if you need to use the theme colorcss
variable, but need to be pre-orderedroot
Define the variables here, I use itvue
Bidirectional binding binds theme colors to:style="{'--color': defaultTheme}"
(See the code above for the specific usage), so that the theme color can be used under any component (Note: This methodIE
The browser does not support it), the code is as follows:
<div class="box"></div>
.box { width: 100px; height: 100px; background-color: var(--color); }
hint:
- If the scss file exports an empty object, you need to change the scss file name to the form.CSS Modules。
- If you need to cache chalkCss, the \ in the css string will be escaped. Remember to manually change it to \\, otherwise the icons that come with ElementUI cannot be displayed.
Reference documentation:
- vue-element-admin Dynamic skinning official document
- ThemePicker component
- CSS variables
How to implement webpack-theme-color-replacer plug-in
This method is available for personal testing, which is essentially a color replacement, but it is also a color replacement, butElementUI
A little compatibility issue, see the specific implementation methodUse of webpack-theme-color-replacer, I won't go into too much detail here.
Summarize
This is the article about Vue+ElementUI dynamically changing any theme color (dynamic skinning) that ends with this article. For more related content related to Vue ElementUI dynamically changing any theme color, please search for my previous article or continue browsing the related articles below. I hope everyone will support me in the future!