最新消息:iOS编程开发交流群(6906921) ,Mac.Cocoa开发交流群(7758675) 欢迎iOS/macOS开发编程爱好及学习者加入!

Vue开发之CDN引入ElementUI后修改主题色的简单方法

JavaScript 天狐 6886浏览 0评论

工程化的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后修改主题色的简单方法

微信 OR 支付宝 扫描二维码
为天狐 打赏
非常感谢你的支持,哥会继续努力!
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址