美文网首页
vue2.x element-ui 适配css var 变量换肤

vue2.x element-ui 适配css var 变量换肤

作者: 奋斗的小蜗牛yyl | 来源:发表于2024-07-22 10:22 被阅读0次

    B端业务中有个需求,不同的客户需要有自己的主题色, element-ui 官网提供的换肤方式不适用与用户自定义切换颜色(别问我为什么不升级,你懂得!),用户能切换的是内置好的,因为客户很多,不可能内置这么多主题。所以决定采用css变量来实现。说干就干~

    1. 根据element-ui官网提供的方案(项目使用的是less,所以使用ele提供的主题工具)

    第一步 安装主题工具和主题(推荐安装在当前项目下)

    
    npm i element-theme element-theme-chalk -D
    
    
    

    第二步 初始化变量文件

    node_modules/.bin/et -i
    
    

    执行后不出意外的话,意外出现了,报错了。。。开始手忙脚乱, 怀疑是不是姿势不对,再来一次还是报错


    image.png

    在网上冲浪了亿会会, 发现是node版本太高导致的 我使用的是14版本,建议是 11.15以下,解决方案有以下两种(冲浪的收获)

     - 安装低版本 node  11.15以下
     - 安装 element-themex
    

    我这里用的是第二种方案 安装 element-themex

    image-1.png

    安装成功后再次执行 node_modules/.bin/et -i

    image-2.png

    这次终于成功了,开心~ !我们可以在根目录下看到 scss 变量文件

    image-3.png

    第三步 修改变量文件 这里把默认色修改为css 变量

    image-4.png
    /* Color
    -------------------------- */
    /// color|1|Brand Color|0
    $--color-primary: var(--customize-theme) !default;
    /// color|1|Background Color|4
    $--color-white: #FFFFFF !default;
    /// color|1|Background Color|4
    $--color-black: #000000 !default;
    
    

    第四步 执行编译主题命令(坐等主题生成 嗯哼!)

    
    node_modules/.bin/et
    
    

    天呐!意外再一次出现,报错了,天塌了!!!!

    image-5.png

    报错提示很明显,scss mix函数的入参需要是一个颜色值。我们传入一个 css 变量它是不支持的。因为ele主题中一些样式使用的是默认颜色与另外一种混合,根据一定的比例混合在一起,生成另一种颜色。于是网上冲浪~~无果!!!
    没办法业务需求要实现,头发还是需要掉。
    经过深思熟虑决定解决这个报错,手动改源码是不可能的,因为颜色是scss编译过程生成的,直接改源码的事就不想聊了~

    2.修改 scss 变量的mix函数

    第一步 实现 mixToVar 函数

    其实ele提供的主题编译工具逻辑很简单,就是把 element-theme-chalk 中的变量暴露出来,供项目修改,修改后再执行编译命令,把修改后的主题文件重写进 element-theme-chalk 中的变量文件,在执行scss编译,把scss文件编译成css文件

    那我们也可以加一层命令,就是把 mix 函数替换掉,替换逻辑很简单,读取element-theme-chalk中的scss文件,使用字符串替换就行,函数名为 mixToVar
    mixToVar 入参与 mix 函数一致,这里不用去关心 mix 函数的内部实现
    mixToVar 函数的需要实现的功能如下

    • 判断入参是否存在css var 函数(可以通过scss字符串提供的方法, str-index())
      • 存在var函数字符串则获取css变量名 和 其他参数进行拼接 返回新的 var() 函数
    • 参数中不存在 var函数 则直接返回 mix 函数

    mixToVar 具体实现如下 主要使用字符串相关的操作 判断索引、截取等

    /* 自定义函数 */
    @function mixToVar($c1, $c2, $percent: 50%) {
    
        $str: '';
        $len: str-index($percent + '', '%');
        $percentNew: $percent;
    
        @if $len {
            $percentNew: str-slice($percent+'', 0, $len - 1)
        }
    
        $c1Str: $c1+'';
        $c2Str: $c2+'';
        $c1VarIdx: str-index($c1Str, 'var(');
        $c2VarIdx: str-index($c2Str, 'var(');
    
        @if $c1VarIdx {
            $str: '#{str-slice($c1Str, str-index($c1Str, '(') + 1, str-index($c1Str, ')') - 1)}'
        }
    
        @else {
            $str: '--YS#{transformColor($c1)}'
        }
    
        @if $c2VarIdx {
            $c2Var: #{str-slice($c2Str,str-index($c2Str, '(') + 1, str-index($c2Str, ')') - 1)};
            $str: $str + '_#{$c2Var}_' + $percentNew;
            @return var(unquote($str));
        }
    
        @if $c1VarIdx {
            $str: $str + '_--YS#{transformColor($c2)}_' + $percentNew;
            @return var(unquote($str));
        }
    
        @return mix($c1, $c2, $percent);
    }
    
    @function transformColor($color) {
        $str: $color+'';
        $idx: str-index($str, '#');
    
        @if $idx {
            @return str-slice($str, $idx+ 1);
        }
    
        @return $color;
    }
    
    // YS 表示颜色值 后续容易分割字符串
    // _ 后续分割字符使用
    
    // mixToVar 返回示例
    
    // 1
    // mixToVar(#409EFF, var(--customize-theme), 60%)
    // 返回结果 var(--YS409EFF_--customize-theme_60)
    
    // 2
    // mixToVar(var(--customize-theme), #409EFF, 60%)
    // 返回结果 var(--customize-theme_--YS409EFF_60)
    
    // 3
    // mixToVar(var(--customize-theme), var(--customize-theme1), 60%)
    // 返回结果 var(--customize-theme_--customize-theme1_60)
    
    // 4
    // mixToVar(#FFFFFF, #409EFF, 10%)
    // 返回结果 #53a8ff
    
    

    第二步 实现主题工具

    函数已经写好了,后面就是替换mix函数, 为了和ele风格保持一致,我这里也简单实现一个命令行工具(需要一点node基础)ele-theme-tool,工具主要是转换 scss 文件
    工具主要功能有下面几点:

    • 替换mix函数同时, 注入写好的 mixToVar 函数
    • 生成当前项目需要用的 主题设置函数
      • 主题设置函数根据变量和颜色和比例生成新的颜色

    因为变量是动态生成的变量,项目是无感的,项目不知道工具生成了那些变量,为了傻瓜式,主题工具生成好js方法

    工具写好后发布,然后安装工具(项目使用less,scss都可以使用它生成element-ui主题)

    npm i ele-theme-tool -D
    
    

    安装成功后执行以下命令进行初始化

    • 执行前请确保 element-ui 主题色没有被定制过,如果定制过重新安装 element-theme-chalk 再执行

    • 如果当前根目录下已经存在 element-variables.scss 先删除再执行

    
    node_modules/.bin/ett -i
    
    

    初始化完成如下图

    image-7.png

    我们可以打开 element-variables.scss看一下是否已经替换完成,且 mixToVar 函数是否注入

    image-11.png

    替换的文件会包含 node_modules/element-theme-chalk 里面的scss文件


    image-8.png

    再次修改element-variables.scss文件

    /* Color
    -------------------------- */
    /// color|1|Brand Color|0
    $--color-primary: var(--customize-theme) !default;
    /// color|1|Background Color|4
    $--color-white: #FFFFFF !default;
    /// color|1|Background Color|4
    $--color-black: #000000 !default;
    
    

    第三步 执行element-ui提供的 主题编译方法 注意是 element-ui 提供的方法

    
    node_modules/.bin/et
    
    

    这一次没有出现意外,成功了!!!!!!!!!趾高气昂!!!!

    image-9.png

    打开生成的主题文件夹theme下的css文件可以看到,替换好的 css var函数

    image-10.png

    第四步 获取变量,并生产主题设置工具

    虽然颜色值已经替换完成,但是可以发现都是一些颜色和变量组成的新变量,无法阅读,也没法在外面设置,所以工具的另外一个作用就是生成一个工具函数,供外部项目使用

    执行ele-theme-tool 提供的命令

    
    node_modules/.bin/ett -s
    
    

    这个命令其实还有设置默认颜色(#409EFF)的功能,颜色设置没有暴露出来,有兴趣的自己实现下

    执行完后可以看到css 文件已经修改

    image-12.png

    项目引入编译好的主题

    
    import "../theme/index.css";
    
    

    运行项目可以发现主题已经修改为默认的主题色 #409EFF

    image-13.png

    那如何动态修改呢?执行完命令后,项目根路径下多了一个 theme-tool-web.js 文件, 在项目中使用它

    image-15.png

    刷新页面可以看到,颜色值已经修改为设置的颜色

    image-14.png

    使用 ColorPicker 颜色选择器,直接切换颜色,也可以正常执行

    image-16.png
    如果使用中遇到问题可以初始化一个新的空项目,定义完主题后,把主题文件夹复制到实际项目中引用(element-ui 提供的自定义工具,其实就是生成了一个 css 目录)

    ele-theme-tool 也可以直接通过js调用方式工作
    例如根据element-ui二次封装的组件库可以使用此方式换肤, 这里就不在赘述,有需求,可以根据源码改造、封装

    const { init, build, varUtil } = require('ele-theme-tool')
    
     init.themeInit({
        targetThemePathRoot,
        themeDir,
        themeVarName,
        themeVarPath,
        message: '初始化主题变量'
    })
    
    build.themeBuild({
        targetThemePathRoot,
        targetFontsRoot,
        themeDir,
        targetThemeVarPath,
        minimize: true,
        out: themeOutDir, 
        themeVarPath: path.resolve('variables.scss')
    },() => {
        varUtil.setDefaultVarColor({
            themeDir:themeOutDir
        })
    })
    
    

    github地址: ele-theme-tool

    总结:可以愉快的自定义主题了,如果需要兼容低版本浏览器,建议考虑其他方案或者使用css-vars-ponyfill适配

    头发没了。。。,有更好的方案,可以再评论区分享下。

    相关文章

      网友评论

          本文标题:vue2.x element-ui 适配css var 变量换肤

          本文链接:https://www.haomeiwen.com/subject/nekdwctx.html