使用element ui 動態更換主題且儲存vuex中
阿新 • • 發佈:2020-08-28
前提準備:專案安裝asss、vuex、
//首先安裝element-theme 在專案中安裝,但是一定是全域性安裝 -g 才能使用 et命令
npm i element-theme -g
//接著安裝主題 (官網有) //可以使用cmd npm安裝 npm i element-theme-chalk -D //也能用git上下載安裝 npm i https://github.com/ElementUI/theme-chalk -D
//接著 在cmd 輸入 et -i // 此時專案會生成一個 element-variables.scss 檔案
et -i <也可以自定義檔名和路徑>
// 成功後會輸出 > Generator variables file
// 使用命令 初始化一下 專案會安裝一個 theme 資料夾 et
//將此檔案中的index.css 引入 main.js 中 import '../theme/index.css';
此時安裝工作已經完畢 開始封裝元件
1、新建元件檔案
//封裝元件內容如下 <template> <div> <el-color-picker class="theme-picker" popper-class="theme-picker-dropdown" v-model="theme" :size="size"> </el-color-picker> </div> </template> <script> import { mapGetters, mapMutations } from 'vuex'; const version = require('element-ui/package.json').version; const ORIGINAL_THEME = '#409EFF'; export default{ name: 'ThemePickerColor', props: { size: { type: String, default: 'small' } }, data() { return { chalk: '', // content of theme-chalk css theme: ORIGINAL_THEME, showSuccess: true // 是否彈出換膚成功訊息 }; }, computed: {
//使用vuex計算屬性實時更新資料 ...mapGetters(['themeColor']), themeColorInfo: { get() { return this.themeColor; }, set(val) { this.SET_THEMECOLOR(val); } } }, mounted() { if (this.themeColor != null) {
//將vuex中的值賦值給宣告的變數中 this.theme = this.themeColor;
//vuex儲存資料 this.SET_THEMECOLOR(this.theme); this.showSuccess = false; } }, watch: { theme(val, oldVal) { if (typeof val !== 'string') return; const themeCluster = this.getThemeCluster(val.replace('#', '')); const originalCluster = this.getThemeCluster(oldVal.replace('#', '')); const getHandler = (variable, id) => { return () => { const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', '')); 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; }; }; 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 (typeof innerText !== 'string') return; style.innerText = this.updateStyle(innerText, originalCluster, themeCluster); }); // 響應外部操作 this.SET_THEMECOLOR(this.theme); if (this.showSuccess) { this.$message({ message: '換膚成功', type: 'success' }); } else { this.showSuccess = true; } } }, methods: { ...mapMutations(['SET_THEMECOLOR']), updateStyle(style, oldCluster, newCluster) { let newStyle = style; oldCluster.forEach((color, index) => { newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index]); }); return newStyle; }, getCSSString(url, callback, variable) { const xhr = new XMLHttpRequest(); xhr.onreadystatechange = () => { if (xhr.readyState === 4 && xhr.status === 200) { this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, ''); callback(); } }; 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) { 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; } } }; </script> <style lang="scss" scoped> </style>
// 元件使用方法 <!-- 自定義主題顏色 --> <div> <el-tooltip effect="dark" content="自定義主題顏色" placement="bottom"> <v-picker v-model="colorPage3"></v-picker> </el-tooltip> </div>
//data中宣告 預設值
colorPage3: '#409EFF'
//在vuex中儲存主題顏色 import vue from 'vue'; import Vuex from 'vuex'; vue.use(Vuex); // 持久化外掛 import createPersistedState from 'vuex-persistedstate'; export default new Vuex.Store({ //定義變數 state: { themeColor: '#409EFF' }, getters: { themeColor(state) { return state.themeColor; } }, mutations: { SET_THEMECOLOR(state, list) { state.themeColor = list; } }, actions: {}, plugins: [ createPersistedState({ storage: window.localStorage }) ] });