vue项目中引入element-ui时,如何更改主题色

在我们做项目时,我们经常会遇到切换主题色的功能,下面我们就来说一下通过颜色选择器我们就能改变项目的主题颜色

代码如下:

颜色选择器所在组件:

top-theme.vue内容如下:

 1 <template>
 2 
 3     <el-color-picker size="small" class="theme-picker" popper-class="theme-picker-dropdown" v-model="themeVal"></el-color-picker>
 4 </template>
 5 
 6 <script>
 7 import theme from "@/mixins/theme";
 8 
 9 export default {
10   name: "topTheme",
11   mixins: [theme()],
12   data() {
13     return {
14       chalk: ""
15     };
16   },
17 
18 };
19 </script>
20 
21 <style scoped>
22 .theme-picker .el-color-picker__trigger {
23   vertical-align: middle;
24 }
25 
26 .theme-picker-dropdown .el-color-dropdown__link-btn {
27   display: none;
28 }
29 </style>
View Code

其中mixins下的theme.js如下:

内容为:

  1 /*
  2  *    Copyright (c) 2018-2025, lengleng All rights reserved.
  3  *
  4  * Redistribution and use in source and binary forms, with or without
  5  * modification, are permitted provided that the following conditions are met:
  6  *
  7  * Redistributions of source code must retain the above copyright notice,
  8  * this list of conditions and the following disclaimer.
  9  * Redistributions in binary form must reproduce the above copyright
 10  * notice, this list of conditions and the following disclaimer in the
 11  * documentation and/or other materials provided with the distribution.
 12  * Neither the name of the pig4cloud.com developer nor the names of its
 13  * contributors may be used to endorse or promote products derived from
 14  * this software without specific prior written permission.
 15  * Author: lengleng (wangiegie@gmail.com)
 16  */
 17 
 18 import {
 19   mapGetters
 20 } from "vuex";
 21 const version = require("element-ui/package.json").version; // element-ui version from node_modules
 22 const ORIGINAL_THEME = "#409EFF"; // default color
 23 export default function () {
 24   return {
 25     data() {
 26       return {
 27         themeVal: ORIGINAL_THEME
 28       }
 29     },
 30     created() {
 31       this.themeVal = this.theme;
 32     },
 33     watch: {
 34       themeVal(val, oldVal) {
 35         this.$store.commit("SET_THEME", val);
 36         this.updateTheme(val, oldVal);
 37       }
 38     },
 39     computed: {
 40       ...mapGetters(["theme"])
 41     },
 42     methods: {
 43       updateTheme(val, oldVal) {
 44         if (typeof val !== "string") return;
 45         const head = document.getElementsByTagName("head")[0];
 46         const themeCluster = this.getThemeCluster(val.replace("#", ""));
 47         const originalCluster = this.getThemeCluster(oldVal.replace("#", ""));
 48         const getHandler = (variable, id) => {
 49           return () => {
 50             const originalCluster = this.getThemeCluster(
 51               ORIGINAL_THEME.replace("#", "")
 52             );
 53             const newStyle = this.updateStyle(
 54               this[variable],
 55               originalCluster,
 56               themeCluster
 57             );
 58 
 59             let styleTag = document.getElementById(id);
 60             if (!styleTag) {
 61               styleTag = document.createElement("style");
 62               styleTag.setAttribute("id", id);
 63               head.appendChild(styleTag);
 64             }
 65             styleTag.innerText = newStyle;
 66           };
 67         };
 68 
 69         const chalkHandler = getHandler("chalk", "chalk-style");
 70 
 71         if (!this.chalk) {
 72           const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`;
 73           this.getCSSString(url, chalkHandler, "chalk");
 74         } else {
 75           chalkHandler();
 76         }
 77 
 78         const link = [].slice.call(
 79           document.getElementsByTagName("head")[0].getElementsByTagName("link")
 80         );
 81         for (let i = link.length - 3; i < link.length; i++) {
 82           const style = link[i];
 83           this.getCSSString(style.href, innerText => {
 84             const originalCluster = this.getThemeCluster(
 85               ORIGINAL_THEME.replace("#", "")
 86             );
 87             const newStyle = this.updateStyle(
 88               innerText,
 89               originalCluster,
 90               themeCluster
 91             );
 92             let styleTag = document.getElementById(i);
 93             if (!styleTag) {
 94               styleTag = document.createElement("style");
 95               styleTag.id = i;
 96               styleTag.innerText = newStyle;
 97               head.appendChild(styleTag);
 98             }
 99           });
100         }
101 
102         const styles = [].slice
103           .call(document.querySelectorAll("style"))
104           .filter(style => {
105             const text = style.innerText;
106             return (
107               new RegExp(oldVal, "i").test(text) && !/Chalk Variables/.test(text)
108             );
109           });
110         styles.forEach(style => {
111           const {
112             innerText
113           } = style;
114           if (typeof innerText !== "string") return;
115           style.innerText = this.updateStyle(
116             innerText,
117             originalCluster,
118             themeCluster
119           );
120         });
121       },
122       updateStyle(style, oldCluster, newCluster) {
123         let newStyle = style;
124         oldCluster.forEach((color, index) => {
125           newStyle = newStyle.replace(new RegExp(color, "ig"), newCluster[index]);
126         });
127         return newStyle;
128       },
129       getCSSString(url, callback, variable) {
130         const xhr = new XMLHttpRequest();
131         xhr.onreadystatechange = () => {
132           if (xhr.readyState === 4 && xhr.status === 200) {
133             if (variable) {
134               this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, "");
135             }
136             callback(xhr.responseText);
137           }
138         };
139         xhr.open("GET", url);
140         xhr.send();
141       },
142       getThemeCluster(theme) {
143         const tintColor = (color, tint) => {
144           let red = parseInt(color.slice(0, 2), 16);
145           let green = parseInt(color.slice(2, 4), 16);
146           let blue = parseInt(color.slice(4, 6), 16);
147 
148           if (tint === 0) {
149             // when primary color is in its rgb space
150             return [red, green, blue].join(",");
151           } else {
152             red += Math.round(tint * (255 - red));
153             green += Math.round(tint * (255 - green));
154             blue += Math.round(tint * (255 - blue));
155 
156             red = red.toString(16);
157             green = green.toString(16);
158             blue = blue.toString(16);
159 
160             return `#${red}${green}${blue}`;
161           }
162         };
163 
164         const shadeColor = (color, shade) => {
165           let red = parseInt(color.slice(0, 2), 16);
166           let green = parseInt(color.slice(2, 4), 16);
167           let blue = parseInt(color.slice(4, 6), 16);
168 
169           red = Math.round((1 - shade) * red);
170           green = Math.round((1 - shade) * green);
171           blue = Math.round((1 - shade) * blue);
172 
173           red = red.toString(16);
174           green = green.toString(16);
175           blue = blue.toString(16);
176 
177           return `#${red}${green}${blue}`;
178         };
179 
180         const clusters = [theme];
181         for (let i = 0; i <= 9; i++) {
182           clusters.push(tintColor(theme, Number((i / 10).toFixed(2))));
183         }
184         clusters.push(shadeColor(theme, 0.1));
185         return clusters;
186       }
187     }
188   }
189 }
View Code

涉及到的vuex相关模块为:

其中validate.js中有一系列正则校验的相关代码:

  1 /*
  2  *    Copyright (c) 2018-2025, lengleng All rights reserved.
  3  *
  4  * Redistribution and use in source and binary forms, with or without
  5  * modification, are permitted provided that the following conditions are met:
  6  *
  7  * Redistributions of source code must retain the above copyright notice,
  8  * this list of conditions and the following disclaimer.
  9  * Redistributions in binary form must reproduce the above copyright
 10  * notice, this list of conditions and the following disclaimer in the
 11  * documentation and/or other materials provided with the distribution.
 12  * Neither the name of the pig4cloud.com developer nor the names of its
 13  * contributors may be used to endorse or promote products derived from
 14  * this software without specific prior written permission.
 15  * Author: lengleng (wangiegie@gmail.com)
 16  */
 17 
 18 /**
 19  * Created by jiachenpan on 16/11/18.
 20  */
 21 
 22 export function isvalidUsername(str) {
 23     const valid_map = ['admin', 'editor']
 24     return valid_map.indexOf(str.trim()) >= 0
 25 }
 26 
 27 /* 合法uri*/
 28 export function validateURL(textval) {
 29     const urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
 30     return urlregex.test(textval)
 31 }
 32 
 33 /* 小写字母*/
 34 export function validateLowerCase(str) {
 35     const reg = /^[a-z]+$/
 36     return reg.test(str)
 37 }
 38 
 39 /* 大写字母*/
 40 export function validateUpperCase(str) {
 41     const reg = /^[A-Z]+$/
 42     return reg.test(str)
 43 }
 44 
 45 /* 大小写字母*/
 46 export function validatAlphabets(str) {
 47     const reg = /^[A-Za-z]+$/
 48     return reg.test(str)
 49 }
 50 /*验证pad还是pc*/
 51 export const vaildatePc = function () {
 52     const userAgentInfo = navigator.userAgent;
 53     const Agents = ["Android", "iPhone",
 54         "SymbianOS", "Windows Phone",
 55         "iPad", "iPod"];
 56     let flag = true;
 57     for (var v = 0; v < Agents.length; v++) {
 58         if (userAgentInfo.indexOf(Agents[v]) > 0) {
 59             flag = false;
 60             break;
 61         }
 62     }
 63     return flag;
 64 }
 65 /**
 66  * validate email
 67  * @param email
 68  * @returns {boolean}
 69  */
 70 export function validateEmail(email) {
 71     const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
 72     return re.test(email)
 73 }
 74 
 75 /**
 76  * 判断身份证号码
 77  */
 78 export function cardid(code) {
 79     let list = [];
 80     let result = true;
 81     let msg = '';
 82     var city = {
 83         11: "北京",
 84         12: "天津",
 85         13: "河北",
 86         14: "山西",
 87         15: "内蒙古",
 88         21: "辽宁",
 89         22: "吉林",
 90         23: "黑龙江 ",
 91         31: "上海",
 92         32: "江苏",
 93         33: "浙江",
 94         34: "安徽",
 95         35: "福建",
 96         36: "江西",
 97         37: "山东",
 98         41: "河南",
 99         42: "湖北 ",
100         43: "湖南",
101         44: "广东",
102         45: "广西",
103         46: "海南",
104         50: "重庆",
105         51: "四川",
106         52: "贵州",
107         53: "云南",
108         54: "西藏 ",
109         61: "陕西",
110         62: "甘肃",
111         63: "青海",
112         64: "宁夏",
113         65: "新疆",
114         71: "台湾",
115         81: "香港",
116         82: "澳门",
117         91: "国外 "
118     };
119     if (!validatenull(code)) {
120         if (code.length == 18) {
121             if (!code || !/(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(code)) {
122                 msg = "证件号码格式错误";
123             } else if (!city[code.substr(0, 2)]) {
124                 msg = "地址编码错误";
125             } else {
126                 //18位身份证需要验证最后一位校验位
127                 code = code.split('');
128                 //∑(ai×Wi)(mod 11)
129                 //加权因子
130                 var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
131                 //校验位
132                 var parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2, 'x'];
133                 var sum = 0;
134                 var ai = 0;
135                 var wi = 0;
136                 for (var i = 0; i < 17; i++) {
137                     ai = code[i];
138                     wi = factor[i];
139                     sum += ai * wi;
140                 }
141                 var last = parity[sum % 11];
142                 if (parity[sum % 11] != code[17]) {
143                     msg = "证件号码校验位错误";
144                 } else {
145                     result = false;
146                 }
147 
148             }
149         } else {
150             msg = "证件号码长度不为18位";
151         }
152 
153     } else {
154         msg = "证件号码不能为空";
155     }
156     list.push(result);
157     list.push(msg);
158     return list;
159 }
160 /**
161  * 判断手机号码是否正确
162  */
163 export function isvalidatemobile(phone) {
164     let list = [];
165     let result = true;
166     let msg = '';
167     var isPhone = /^0\d{2,3}-?\d{7,8}$/;
168     //增加134 减少|1349[0-9]{7},增加181,增加145,增加17[678]
169     var isMob = /^((\+?86)|(\(\+86\)))?(13[0123456789][0-9]{8}|15[012356789][0-9]{8}|18[012356789][0-9]{8}|14[57][0-9]{8}|17[3678][0-9]{8})$/;
170     if (!validatenull(phone)) {
171         if (phone.length == 11) {
172             if (isPhone.test(phone)) {
173                 msg = '手机号码格式不正确';
174             } else {
175                 result = false;
176             }
177         } else {
178             msg = '手机号码长度不为11位';
179         }
180     } else {
181         msg = '手机号码不能为空';
182     }
183     list.push(result);
184     list.push(msg);
185     return list;
186 }
187 /**
188  * 判断姓名是否正确
189  */
190 export function validatename(name) {
191     var regName = /^[\u4e00-\u9fa5]{2,4}$/;
192     if (!regName.test(name)) return false;
193     return true;
194 };
195 /**
196  * 判断是否为整数
197  */
198 export function validatenum(num, type) {
199     let regName = /[^\d.]/g;
200     if (type == 1) {
201         if (!regName.test(num)) return false;
202     } else if (type == 2) {
203         regName = /[^\d]/g;
204         if (!regName.test(num)) return false;
205     }
206     return true;
207 };
208 /**
209  * 判断是否为小数
210  */
211 export function validatenumord(num, type) {
212     let regName = /[^\d.]/g;
213     if (type == 1) {
214         if (!regName.test(num)) return false;
215     } else if (type == 2) {
216         regName = /[^\d.]/g;
217         if (!regName.test(num)) return false;
218     }
219     return true;
220 };
221 /**
222  * 判断是否为空
223  */
224 export function validatenull(val) {
225     if (val instanceof Array) {
226         if (val.length == 0) return true;
227     } else if (val instanceof Object) {
228         if (JSON.stringify(val) === '{}') return true;
229     } else {
230         if (val == 'null' || val == null || val == 'undefined' || val == undefined || val == '') return true;
231         return false;
232     }
233     return false;
234 
235 };
View Code

utils下store.js内容如下:

 1 /*
 2  *    Copyright (c) 2018-2025, lengleng All rights reserved.
 3  *
 4  * Redistribution and use in source and binary forms, with or without
 5  * modification, are permitted provided that the following conditions are met:
 6  *
 7  * Redistributions of source code must retain the above copyright notice,
 8  * this list of conditions and the following disclaimer.
 9  * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * Neither the name of the pig4cloud.com developer nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  * Author: lengleng (wangiegie@gmail.com)
16  */
17 
18 import { validatenull } from '@/utils/validate'
19 /**
20  * 存储localStorage
21  */
22 export const setStore = (params) => {
23   const {
24     name,
25     content,
26     type,
27     datetime
28   } = params
29   const obj = {
30     dataType: typeof (content),
31     content: content,
32     type: type,
33     datetime: new Date().getTime()
34   }
35   if (type) window.sessionStorage.setItem(name, JSON.stringify(obj))
36   else window.localStorage.setItem(name, JSON.stringify(obj))
37 }
38 /**
39  * 获取localStorage
40  */
41 export const getStore = (params) => {
42   const {
43     name,
44     type
45   } = params
46   let obj = {}
47   let content
48   obj = window.localStorage.getItem(name)
49   if (validatenull(obj)) obj = window.sessionStorage.getItem(name)
50   if (validatenull(obj)) return
51   obj = JSON.parse(obj)
52   if (obj.dataType === 'string') {
53     content = obj.content
54   } else if (obj.dataType === 'number') {
55     content = Number(obj.content)
56   } else if (obj.dataType === 'boolean') {
57     content = eval(obj.content)
58   } else if (obj.dataType === 'object') {
59     content = obj.content
60   }
61   return content
62 }
63 /**
64  * 删除localStorage
65  */
66 export const removeStore = params => {
67   let {
68     name
69   } = params
70   window.localStorage.removeItem(name)
71   window.sessionStorage.removeItem(name)
72 }
View Code

store文件夹下index.js内容如下:

 1 /**
 2  * Created by xieli on 2018/8/7 0007.
 3  */
 4 import Vue from 'vue'
 5 import Vuex from 'vuex'
 6 import common from './modules/common'
 7 import getters from './getters'
 8 
 9 Vue.use(Vuex)
10 const store = new Vuex.Store({
11     modules: {
12         common,
13     },
14     getters,
15 })
16 
17 export default store
View Code
modules文件夹下common.js内容如下:
 1 /*
 2  *    Copyright (c) 2018-2025, lengleng All rights reserved.
 3  *
 4  * Redistribution and use in source and binary forms, with or without
 5  * modification, are permitted provided that the following conditions are met:
 6  *
 7  * Redistributions of source code must retain the above copyright notice,
 8  * this list of conditions and the following disclaimer.
 9  * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * Neither the name of the pig4cloud.com developer nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  * Author: lengleng (wangiegie@gmail.com)
16  */
17 
18 import {
19     setStore,
20     getStore,
21     removeStore
22 } from '@/utils/store'
23 import {
24     validatenull
25 } from '@/utils/validate'
26 
27 
28 const common = {
29 
30   state: {
31     theme: getStore({
32       name: 'theme'
33     }) || '#409EFF',
34       bg:"主题颜色"
35   },
36   mutations: {
37       SET_THEME: (state, color) => {
38       state.theme = color
39       setStore({
40         name: 'theme',
41         content: state.theme
42       })
43     },
44 
45   }
46 }
47 export default common
View Code

store文件夹下getters.js内容如下:

 1 /*
 2  *    Copyright (c) 2018-2025, lengleng All rights reserved.
 3  *
 4  * Redistribution and use in source and binary forms, with or without
 5  * modification, are permitted provided that the following conditions are met:
 6  *
 7  * Redistributions of source code must retain the above copyright notice,
 8  * this list of conditions and the following disclaimer.
 9  * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * Neither the name of the pig4cloud.com developer nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  * Author: lengleng (wangiegie@gmail.com)
16  */
17 
18 const getters = {
19   theme: state => state.common.theme,
20     /*bg:    state => state.common.bg,*/
21 
22 }
23 export default getters
View Code

其中核心文件为mixins下的theme.js

项目地址:

https://github.com/yuwenjing0727/electric-ui.git

 

posted @ 2018-08-09 17:39  yuwenjing  阅读(15839)  评论(3编辑  收藏  举报