工程化的Vue项目cdn引入Vue.js和ElementUI方法很简单,不再赘述。
ElementUI提供的样式中,默认的主题色是一种蓝色。工程化的ElementUI主题样式一般都是用sass变量指定,比如
/* 改变主题色变量 */ $--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的默认样式。
<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中,使样式生效。
import ElementTheme from '../utils/ElementTheme' mounted () { ElementTheme.changeTheme("#000000"); }
以下是我调试好的工具类。
//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后修改主题色的简单方法