工程化的Vue项目cdn引入Vue.js和ElementUI方法很简单,不再赘述。
ElementUI提供的样式中,默认的主题色是一种蓝色。工程化的ElementUI主题样式一般都是用sass变量指定,比如
1 2 3 4 5 6 7 8 |
/* 改变主题色变量 */ $--color-primary: $primaryColor; $--color-success: $successColor; $--color-warning: $warningColor; $--color-danger: $errorColor; /* 引用nodemodules中的样式 */ @import "~element-ui/packages/theme-chalk/src/index"; |
CDN模式下直接在index.html中引用如下css即可应用ElementUI的默认样式。
1 |
<link rel='stylesheet' id="chalk-style" href='https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/element-ui/2.15.7/theme-chalk/index.css' type='text/css' media='all' /> |
但是一般的vue项目主题色需要自己指定,然而ElementUi又没有提供配置方法。
有人可能知道,ElementUi提供了在线diy主题css的方法 主题生成工具。
这种方式能解决问题,包括下载/theme-chalk/index.css修改后工程中引用。
还有人直接把elementui源码拉了下来,改动主题色变量后编译出来引用。
但是最大的问题是css文件还是要引用到项目中。那使用cdn优化的意义是什么呢?
方案
所以我研究下了,大致思路可以是在vue项目开始访问的时候,动态的js下载/theme-chalk/index.css,脚本替换颜色变量,替换字体为绝对路径,后再append到head中,使样式生效。
1 2 3 4 5 |
import ElementTheme from '../utils/ElementTheme' mounted () { ElementTheme.changeTheme("#000000"); } |
以下是我调试好的工具类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
//element ui cdn css const cdn = 'https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M'; const url = `${cdn}/element-ui/2.15.7/theme-chalk/index.css`; //font url const fontUrl = `${cdn}/element-ui/2.15.7/theme-chalk/fonts/element-icons`; //默认蓝色主题 const ORIGINAL_THEME = "#409EFF"; export default{ data: { chalk: "", theme: "", url:url }, changeTheme(val) { if (typeof val !== "string" || !val) return; var that = this; that.data.theme = val; //新色 const themeCluster = this.getThemeCluster(val.replace("#", "")); //原色 const originalCluster = this.getThemeCluster( ORIGINAL_THEME.replace("#", "") ); const getHandler = (variable, id) => { return () => { const newStyle = this.updateStyle( that.data[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 chalkHandler = getHandler("chalk", "chalk-style"); // 判断是否已有样式表,没有则根据url请求样式表内容 if (!this.data.chalk) { this.getCSSString(this.data.url, chalkHandler, "chalk"); } else { chalkHandler(); } }, // 更新主题系列色 updateStyle(style, oldCluster, newCluster) { let newStyle = style; oldCluster.forEach((color, index) => { newStyle = newStyle.replace(new RegExp(color, "ig"), newCluster[index]); }); return newStyle; }, // 初始化时获取默认主题的样式并复制给this.chalk getCSSString(url, callback, variable) { const xhr = new XMLHttpRequest(); var that = this; xhr.onreadystatechange = () => { if (xhr.readyState === 4 && xhr.status === 200) { // that.data[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, ""); that.data[variable] = xhr.responseText.replace('fonts/element-icons', fontUrl); 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; }, // /移除全局css removeGlobalCSS: function (id) { var head = document.head || document.getElementsByTagName('head')[0]; // 获取head元素 setTimeout(function () { var tempElement = document.getElementById(id); if (tempElement) { head.removeChild(tempElement); } }, 200) }, } |
解决上线!
转载请注明:天狐博客 » Vue开发之CDN引入ElementUI后修改主题色的简单方法