vue,css线上换肤color方案,支持预设申明和全局颜色匹配替换

240 阅读2分钟

来补充一下,新的方案,不考虑兼容的话,css变量是最好的方案。

==============================================================================================

方案一:

使用element换肤方案,原理是less变量,预先提取所有文件的less文件,在线上用js替换less变量,添加到文档上。

方案二:

使用stylesheet

 /**
     * @desc 换肤方法
     * @param {object} colorData 需要替换颜色的键值对
     */
    changeColors(colorData) {
       window.onload=function(){
        console.log("开始换肤"+(new Date()).valueOf())
        var styleSheets=document.styleSheets
        var styleSheet;
        //预处理,兼容原先color配置文件,16进制转换为rgb,支持rgba和rgb逗号后需要空格,不支持16进制透明度
        //后续支持css全局变量可以按照需求转变
        var newColorData={}
        for(var key in colorData){
            var newkey;
            if (key.substr(0, 1) == "#"){
                key = key.substring(1);
            key = key.toLowerCase();
            var b = new Array();
            for (var x = 0; x < 3; x++) {
                b[0] = key.length == 6 ? key.substr(x * 2, 2) : key.substr(x * 1, 1) + key.substr(x * 1, 1);
                b[3] = "0123456789abcdef";
                b[1] = b[0].substr(0, 1);
                b[2] = b[0].substr(1, 1);
                b[20 + x] = b[3].indexOf(b[1]) * 16 + b[3].indexOf(b[2])
            }
            newkey="rgb\\("+b[20]+",\\s"+b[21]+",\\s"+b[22]+"\\)"
            newColorData[newkey] = colorData['#'+key]
            }else if(key.substr(0, 1) == "@"){
                switch(key){
                //需要匹配的自定义字段
                    case "@primary-color":newColorData["rgb\\(53,\\s152,\\s219\\)"] = colorData[key];break;
                    default: break;
                }
            }else if(key.substr(0, 3) == "rgb"){
                newkey=key.replace(/[(]/g,"\\(").replace(/[ ]/g,"\\s").replace(/[)]/g,"\\)")
                newColorData[newkey] = colorData[key]
            }
        
        }
        var regtest;
        var longStr = ''
        for(let i=0;i<styleSheets.length;i++){
            styleSheet = styleSheets[i]
            for(let j=0;j<styleSheet.cssRules.length;j++){
                    longStr += styleSheet.cssRules[j].cssText+"&"
            }
        }
        for(var key in newColorData){
            regtest = new RegExp(key,'g')
            longStr=longStr.replace(regtest,newColorData[key])
        }
        longStr=longStr.split('&')
        var flag=0
        for(let i=0;i<styleSheets.length;i++){
            styleSheet = styleSheets[i]
            for(let j=0;j<styleSheet.cssRules.length;j++){
                styleSheet.insertRule(longStr[flag++],j)
                styleSheet.deleteRule(j+1)
            }
        }
        console.log("换肤结束"+ (new Date()).valueOf())
       }
    }
}

优点

无需扫描提取所有样式,减少了打包体积,避免了样式覆盖,允许使用scoped。 使用方便,直接引用方法无需额外配置。

速度快。

缺点

不支持style内联样式,暂时不支持@XXX全局变量。 未经测试的稳定性。

预设申明

方法里没写,可以自行添加css全局变量来实现色值变量

//换肤举例
{
"#f8f8f8":"#0000ff""rgb(250, 250, 250)":"#0000ff",
"@primary-color":"#0000ff"
}