最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 动态修改element-ui主题

    正文概述 掘金(追旅)   2021-04-02   1226

    更多文章

    前言

    ui库搭建的差不多了,接下来就是做组件的时候了,这里先做一个动态修改element-ui颜色的组件库

    分析

    element-ui提供了一个修改主题的方式(网上资料很多,这里不再赘述),就是修改scss变量,但这个是静态的,也就是你在代码运行前需要将这些配置都完成才能生效,项目启动成功后,我们加载的就是编译压缩后的css文件,如果要动态修改主题的话,通常做法就是生成一份新的样式,然后生成新的style标签并加入DOM中,覆盖之前的样式

    实现

    接收一个初始化主题色的参数defaultColor

    props: {
        defaultColor: {
          type: String
        }
    }
    

    为保障element-uicss版本的正确,我们从element-ui/package.json中读取版本

    const version = require("element-ui/package.json").version; // 版本号
    const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`;
    

    即使访问CDN也仍有可能有网络的问题,所以我们也接受动态传入url

    // 默认访问CDN资源
    props: {
        url: {
          type: String,
          default: url
        }
    }
    

    即使动态改变主题,刷新后颜色亦会重置,所以我们接收一个isCache入参,决定是否缓存,缓存方案采用localStorage

    // 默认不缓存
    props: {
        isCache: {
          type: Boolean,
          default: false,
        }
    }
    

    接下来的主要逻辑(看代码吧):

    1. 调用getThemeCluster获取新旧心裂颜色
    2. 首次进入判断this.chalk是否已经缓存样式表内容,没有则调用getCSSString方法获取样式
    3. 调用updateStyle更新并获取最新的样式表内容
    4. 判断是否存在idchalk-stylestyle的标签,没有则生成,有则赋值最新的样式表并加入DOM

    完整代码

    
    <template>
      <el-color-picker
        :size="size"
        v-model="theme"
        class="theme-picker"
        @change="onChange"
        :predefine="predefineColors"
        popper-class="theme-picker-dropdown"
      >
      </el-color-picker>
    </template>
     
    <script>
    const version = require("element-ui/package.json").version; // 版本号
    const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`;
    const ORIGINAL_THEME = "#409EFF";
    
    export default {
      name: "QjdTheme",
      data() {
        return {
          chalk: "",
          theme: "",
          predefineColors: Object.freeze([
            "#409EFF",
            "#ff4500",
            "#ff8c00",
            "#ffd700",
            "#90ee90",
            "#00ced1",
            "#1e90ff",
            "#c71585",
            "rgba(255, 69, 0, 0.68)",
            "rgb(255, 120, 0)",
            "hsv(51, 100, 98)",
            "hsva(120, 40, 94, 0.5)",
            "hsl(181, 100%, 37%)",
            "hsla(209, 100%, 56%, 0.73)",
            "#c7158577",
          ]),
        };
      },
      props: {
        size: {
          type: String,
          default() {
            return "";
          },
        },
        defaultColor: {
          type: String,
        },
        isCache: {
          type: Boolean,
          default: false,
        },
        url: {
          type: String,
          default: url
        }
      },
      mounted() {
        const colorPicker = localStorage.getItem("colorPicker");
        const { defaultColor } = this;
        // 主题色优先级localStorage.getItem("colorPicker") > defaultColor > ORIGINAL_THEME
        this.theme = this.CheckIsColor(colorPicker)
          ? colorPicker
          : this.CheckIsColor(defaultColor)
          ? defaultColor
          : ORIGINAL_THEME;
      },
      watch: {
        theme(val) {
          if (typeof val !== "string" || !val) return;
          this.isCache && localStorage.setItem("colorPicker", val);
          const themeCluster = this.getThemeCluster(val.replace("#", ""));
          const originalCluster = this.getThemeCluster(
            ORIGINAL_THEME.replace("#", "")
          );
          const getHandler = (variable, id) => {
            return () => {
              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 chalkHandler = getHandler("chalk", "chalk-style");
          // 判断是否已有样式表,没有则根据url请求样式表内容
          if (!this.chalk) {
            this.getCSSString(this.url, chalkHandler, "chalk");
          } else {
            chalkHandler();
          }
        },
      },
    
      methods: {
        // 清除缓存
        clearCache() {
          localStorage.removeItem("colorPicker");
        },
        // 颜色改变
        onChange(e) {
          if (e) {
            this.theme = e;
          }
        },
        // 判断是否为颜色
        CheckIsColor(bgVal) {
          if (bgVal) {
            var type = "^#[0-9a-fA-F]{6}$";
            var re = new RegExp(type);
            if (bgVal.match(re) == null) {
              type =
                "^[rR][gG][Bb][(]([\\s]*(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?)[\\s]*,){2}[\\s]*(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)[\\s]*[)]{1}$";
              re = new RegExp(type);
              if (bgVal.match(re) == null) {
                return false;
              } else {
                return true;
              }
            } else {
              return true;
            }
          }
        },
        // 更新主题系列色
        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();
          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>
    

    API

    Attributes

    参数说明类型可选值默认值
    defaultColor默认主题String--size尺寸大小Stringmedium、small、mini-isCache是否开启缓存Boolean-falseurl加载资源地址String-unpkg.com/element-ui@…

    Methods

    方法名说明参数
    clearCache清楚缓存-

    结语

    good good study!!!


    起源地下载网 » 动态修改element-ui主题

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元