增城高端网站建设,电商网站建设考试,网站模板打包下载,查logo的网站接上一篇《前端组件库自定义主题切换探索-02-webpack-theme-color-replacer webpack 的实现逻辑和原理-02》 这篇我们来开始改造#xff0c;让这个插件最终能达到我们的目的#xff1a;
首先修改plugin.config.js。
插件首先要在vue.config.js引用注册#xff0c;因此先对…接上一篇《前端组件库自定义主题切换探索-02-webpack-theme-color-replacer webpack 的实现逻辑和原理-02》 这篇我们来开始改造让这个插件最终能达到我们的目的
首先修改plugin.config.js。
插件首先要在vue.config.js引用注册因此先对这里做改造。这里我们指定了四种颜色primary,danger,warning,other然后生成配置数据数据格式如下
{primary: {matchColors: getAntdSerials(colorTypes[type]), // colors array for extracting css file, support rgb and hsl.fileName: css/${type}-colors-[contenthash:8].css, // optional. output css file name, suport [contenthash] and [hash].configVar: tc_cfg_${type} Math.random().toString().slice(2),
}
}后面的代码逻辑都会根据对象的键名比如primary来读取每个键名下面的配置来做批量操作
最终代码如下
const ThemeColorReplacer require(./webpack-theme-color-replacer/src/index)
// const ThemeColorReplacer require(webpack-theme-color-replacer)
const generate require(ant-design/colors/lib/generate).defaultconst getAntdSerials (color) {// 淡化即less的tintconst lightens new Array(9).fill().map((t, i) {return ThemeColorReplacer.varyColor.lighten(color, i / 10)})// console.log(lightens, lightens)const colorPalettes generate(color)// console.log(colorPalettes, colorPalettes)const rgb ThemeColorReplacer.varyColor.toNum3(color.replace(#, )).join(,)// console.log(rgb, rgb)const matchColors lightens.concat(colorPalettes).concat(rgb)// console.log(matchColors, matchColors)return matchColors
}
const getRandomString () Math.random().toString().slice(2)
const colorTypes {primary: #1890ff,danger: #F5222D,warning: #F2A830,other: #35964f,
}
const option {}
for (const type in colorTypes) {option[type] {matchColors: getAntdSerials(colorTypes[type]), // colors array for extracting css file, support rgb and hsl.fileName: css/${type}-colors-[contenthash:8].css, // optional. output css file name, suport [contenthash] and [hash].configVar: tc_cfg_${type} getRandomString(),}
}
const createThemeColorReplacerPlugin () new ThemeColorReplacer({option
})module.exports createThemeColorReplacerPlugin
在这个验证测试代码过程中也遇到了不少问题这里为了省事点我们就不赘述中间的曲折直接上改好的代码后面再附加一些注意的地方
第二个改scr下面的index.js
这个文件主要是根据option生成LC_THEME_CONFIG变量里面的内容关键代码是 const { option } this.handler.optionsfor (const i in option) {webpackDefineConfig[i] option[i].configVar}new webpack.DefinePlugin({LC_THEME_CONFIG: JSON.stringify(webpackDefineConfig)}).apply(compiler)完整的代码如下
use strict
var Handler require(./handler)var webpack require(webpack)class ThemeColorReplacer {constructor(options) {this.handler new Handler(options)}getBinder(compiler, event) {return compiler.hooks? compiler.hooks[event].tapAsync.bind(compiler.hooks[event], ThemeColorReplacer): compiler.plugin.bind(compiler, event)}apply(compiler) {const webpackDefineConfig {}const { option } this.handler.optionsfor (const i in option) {webpackDefineConfig[i] option[i].configVar}new webpack.DefinePlugin({LC_THEME_CONFIG: JSON.stringify(webpackDefineConfig)}).apply(compiler)compiler.hooks.thisCompilation.tap(ThemeColorReplacer, (compilation) {compilation.hooks.processAssets.tapAsync({name: ThemeColorReplacer,stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS},(compilationAssets, callback) {this.handler.handle(compilation)callback()})})}
}ThemeColorReplacer.varyColor require(../client/vary-color)module.exports ThemeColorReplacer
第三改造index.js直接引用的Handler.js
这里需要改造的关键地方是 const { option } this.options// let { injectToHtml } this.optionsfor (const i in option) {const { fileName, matchColors, configVar } option[i]const output this.assetsExtractor.extractAssets(compilation.assets, matchColors, i)// console.log(handle output, output)// console.log(Extracted theme color css content length: output.length)const outputName compilation.getPath(replaceFileName(fileName, output), {})this.emitSource(compilation, outputName, new wpSources.RawSource(output))// console.log(fileName, fileName)// console.log(matchColors, matchColors)// 记录动态的文件名到每个入口js// console.log(outputName, outputName)this.addToEntryJs(outputName, compilation, output, matchColors, configVar)}另外其他地方需要传递matchColors和configVar之前因为只改一种颜色所以是直接用最外面传递进来的现在要改变多个则需要在for循环里面传递最终修改代码如下
use strict
var webpack require(webpack)
var AssetsExtractor require(./assets-extractor)
var replaceFileName require(./replace-file-name)
var LineReg /\n/g
var wpSources webpack.sources
if (!wpSources) {wpSources require(webpack-sources) // for webpack 4
}
module.exports class Handler {constructor(options) {this.options {isJsUgly: !(process.env.NODE_ENV development || process.argv.find(arg arg.match(/\bdev/))),...options}this.assetsExtractor new AssetsExtractor(this.options.isJsUgly, this.options.changeSelector)}// Add Webpack5 SupportemitSource(compilation, name, source) {console.log(emitSource name, name)var exists compilation.assets[name]if (compilation.updateAsset) { // webpack.version[0] 5if (exists) compilation.updateAsset(name, source)else compilation.emitAsset(name, source)} else {if (exists) delete compilation.assets[name]compilation.assets[name] source}}handle(compilation) {// Add to assets for outputconst { option } this.options// let { injectToHtml } this.optionsfor (const i in option) {const { fileName, matchColors, configVar } option[i]const output this.assetsExtractor.extractAssets(compilation.assets, matchColors, i)// console.log(handle output, output)// console.log(Extracted theme color css content length: output.length)const outputName compilation.getPath(replaceFileName(fileName, output), {})this.emitSource(compilation, outputName, new wpSources.RawSource(output))// console.log(fileName, fileName)// console.log(matchColors, matchColors)// 记录动态的文件名到每个入口js// console.log(outputName, outputName)this.addToEntryJs(outputName, compilation, output, matchColors, configVar)}}// 自动注入js代码设置css文件名addToEntryJs(outputName, compilation, cssCode, matchColors, configVar) {const onlyEntrypoints {entrypoints: true,errorDetails: false,modules: false,assets: false,children: false,chunks: false,chunkGroups: false}const entrypoints compilation.getStats().toJson(onlyEntrypoints).entrypointsObject.keys(entrypoints).forEach(entryName {const entryAssets entrypoints[entryName].assetsfor (let i 0, l entryAssets.length; i l; i) {const assetName entryAssets[i].name || entryAssets[i]if (assetName.slice(-3) .js assetName.indexOf(manifest.) -1) { //const assetSource compilation.assets[assetName]if (assetSource !assetSource._isThemeJsInjected) {const cSrc this.getEntryJs(outputName, assetSource, cssCode, matchColors, configVar)// cSrc._isThemeJsInjected truethis.emitSource(compilation, assetName, cSrc)break}}}})}getConfigJs(outputName, cssCode, matchColors, configVar) {const config { url: outputName, colors: matchColors }if (this.options.injectCss) {config.cssCode cssCode.replace(LineReg, )}return \n(typeof windowundefined?global:window). configVar JSON.stringify(config) ;\n}getEntryJs(outputName, assetSource, cssCode, matchColors, configVar) {const ConcatSource wpSources.ConcatSourceconst CachedSource wpSources.CachedSourceconst configJs this.getConfigJs(outputName, cssCode, matchColors, configVar)if (assetSource instanceof CachedSource) { // CachedSource没有node方法会报错return new CachedSource(concatSrc(assetSource._source || assetSource.source(), configJs))}return concatSrc(assetSource, configJs)function concatSrc(assetSource, configJs) {if (assetSource instanceof ConcatSource) {assetSource.add(configJs)return assetSource} else {return new ConcatSource(assetSource, configJs)}}}
}
这里需要注意的是在addToEntryJs函数里面需要吧cSrc._isThemeJsInjected true去掉。这里是之前插件为了做缓存用的在测试中发现加上这一行window里面最多挂两个tc_cfg_变量 在原本的判断里面执行cSrc._isThemeJsInjected true时assetSource._isThemeJsInjected 也会变为true因为this.getEntryJs返回的是一个浅拷贝且和assetSource同源从下面的代码可以看到数据的来源 数据最终通过webpack处理而来至于为什么是浅拷贝是同源的没有得去深究。
replace-file-name 不需要更改源代码即可。
第四需要改的是assets-extractor.js
原插件是AssetsExtractor这里为了符合开发规范改了名字文件。这里没有大改的地方而是将参数改为从调用的地方传递而不是直接取自option改动后代码如下
var Extractor require(./extractor)
var cssLoaderRegDev /\bn?(?:exports|___CSS_LOADER_EXPORT___)\.push\(\[module\.id?, \\?(.?\})(?:\\?\\n)?(?:[\\n]*\/\*#\s*sourceMappingURL.?\*\/)?\\?, \\?\\?(?:\]\)|,\s*\{)/g// css-loader: n.exportst(FZf)(!1)).push([n.i,\n.payment-type[data-v-ffb10066] {......}\n,])
var cssLoaderRegUgly /\.push\(\[\w\.i,[](.?\})[\\rn]*[],[][](?:\]\)|,\{)/g
var CssExtReg /\.css$/i; var JsExtReg /\.js$/i
function assetToStr(asset) {var src asset.source() || return src.toString()
}
const extractAsset function (fn, asset, matchColors, isJsUgly, changeSelector) {const src assetToStr(asset)var cssSrcs []var CssCodeReg isJsUgly ? cssLoaderRegUgly : cssLoaderRegDevsrc.replace(CssCodeReg, (match, $1) {cssSrcs cssSrcs.concat(Extractor(changeSelector, $1, matchColors))})// console.log(cssSrcs, cssSrcs.filter(itemitem))return cssSrcs.filter(item item)
}
function extractAll(assets, matchColors, isJsUgly, changeSelector, type) {// console.log(extractAll matchColors, matchColors)var cssSrcs []Object.keys(assets).map(fn {// 原本每修改一点源码都需要对整个项目的assets翻一遍css影响性能。// 故改为在asset上缓存上一次的结果对没发生变化的asset直接取缓存(已发生变化的asset已经是新对象无缓存)。// console.log(fn, fn)const asset assets[fn]// console.log(asset._themeCssCache, asset._themeCssCache)let cssRules if (asset._themeCssCache asset._themeCssCache[type]) {cssRules asset._themeCssCache[type]} else {cssRules extractAsset(fn, asset, matchColors, isJsUgly, changeSelector)}// asset._themeCssCache || extractAsset(fn, asset, matchColors, isJsUgly, changeSelector)// console.log(cssRules, cssRules)if (asset._themeCssCache) {asset._themeCssCache[type] cssRules} else {asset._themeCssCache {[type]: cssRules}}cssSrcs cssSrcs.concat(cssRules)})// console.log(cssSrcs, cssSrcs)// console.log(cssSrcs.filter(item item), cssSrcs.filter(item item))return cssSrcs
}module.exports function AssetsExtractor(isJsUgly, changeSelector) {this.extractAssets function (assets, matchColors, type) {// console.log(assets, assets)var srcArray this.extractToArray(assets, matchColors, type)// console.log(srcArray, srcArray)// 外部的css文件。如cdn加载的var output dropDuplicate(srcArray).join(\n)return output}this.extractToArray function (assets, matchColors, type) {var srcArray extractAll(assets, matchColors, isJsUgly, changeSelector, type)// console.log(srcArray------------------------------------------------------, srcArray)if (srcArray.length 0 !this._uglyChanged) {// 容错一次this._uglyChanged trueisJsUgly !isJsUgly// 清空缓存Object.keys(assets).map(fn assets[fn]._themeCssCache 0)srcArray extractAll(assets, matchColors, isJsUgly, changeSelector, type)}return srcArray}
}function dropDuplicate(arr) {var map {}var r []for (var s of arr) {if (!map[s]) {r.push(s)map[s] 1}}return r
}
这里需要注意的一点是asset._themeCssCache 需要按照外面传递的类型来存储否则后面的颜色不生效 const asset assets[fn]// console.log(asset._themeCssCache, asset._themeCssCache)let cssRules if (asset._themeCssCache asset._themeCssCache[type]) {cssRules asset._themeCssCache[type]} else {cssRules extractAsset(fn, asset, matchColors, isJsUgly, changeSelector)}// asset._themeCssCache || extractAsset(fn, asset, matchColors, isJsUgly, changeSelector)// console.log(cssRules, cssRules)if (asset._themeCssCache) {asset._themeCssCache[type] cssRules} else {asset._themeCssCache {[type]: cssRules}}
第五需要改的是assets-extractor.js直接引用的extractor.js。
这里需要改动的是将matchColors从外部直接传入而不是从option取用 改动后代码如下
var extractorCss require(./css-extractor)
const testCssCode function (cssCode, matchColors) {var matchColorRegs matchColors // [#409EFF, #409eff, #53a8ff, #66b1ff, #79bbff, #8cc5ff, #a0cfff, #b3d8ff, #c6e2ff, #d9ecff, #ecf5ff, #3a8ee6, #337ecc].map(c new RegExp(c.replace(/\s/g, ).replace(/,/g, ,\\s*) ([\\da-f]{2})?(\\b|\\)|,|\\s), i)) // 255, 255,3for (var colorReg of matchColorRegs) {if (colorReg.test(cssCode)) return true // !ExclueCssReg.test(cssCode)}return false
}
module.exports function Extractor(changeSelector, src, matchColors) {return extractorCss(src, changeSelector).map(function (css) {var rules css.rules.filter(cssCode testCssCode(cssCode, matchColors))if (!rules.length) return return css.selector { rules.join(;) }})
}
第六个需要改的是extractor.js直接引用的css-extractor.js
同样是需要改动传参方式最终代码如下
// \n和备注
var regLfRem /\\\\?n|\n|\\\\?t|\\\\?r|\/\*[\s\S]?\*\//gvar SpaceReg /\s/g
var TrimReg /(^|,)\s|\s($)/g // 前空格逗号后的空格; 后空格
var SubCssReg /\s*\s*/g // div a 替换为 diva
var DataUrlReg /url\s*\([\\\s]*data:/ // url(data:image/svgxml;base64,PHN2)
var QuotReg /\\([])/g
// var ExclueCssReg /(?:scale3d|translate3d|rotate3d|matrix3d)\s*\(/i;
module.exports function extractCss(src, changeSelector) {src src.replace(regLfRem, )var ret []var nameStart; var nameEnd; var cssEnd -1while (true) {nameStart cssEnd 1nameEnd src.indexOf({, nameStart)cssEnd findCssEnd(src, nameEnd)if (cssEnd -1 cssEnd nameEnd nameEnd nameStart) {var cssCode src.slice(nameEnd 1, cssEnd)if (cssCode.indexOf({) -1) { // keyframesvar rules extractCss(cssCode, changeSelector)} else {rules getRules(cssCode)}if (rules.length) {var selector src.slice(nameStart, nameEnd)selector selector.replace(TrimReg, $1)selector selector.replace(SubCssReg, )selector selector.replace(SpaceReg, ) // linesvar p selector.indexOf(;) // charset utf-8;if (p -1) {selector selector.slice(p 1)}// 改变选择器if (changeSelector) {var util {rules: rules,changeEach: changeEach}selector changeSelector(selector.split(,).sort().join(,), util) || selector}ret.push({ selector, rules: rules })}} else {break}}return ret// 查找css尾部兼容 keyframes {10%{...}}function findCssEnd(src, start) {var level 1var cssEnd startwhile (true) {cssEndvar char src[cssEnd]if (!char) {return -1} else if (char {) {level} else if (char }) {level--if (level 0) {break}}}return cssEnd}function changeEach(selector, surfix, prefix) {surfix surfix || prefix prefix || return selector.split(,).map(function (s) {return prefix s surfix}).join(,)}
}function getRules(cssCode) {var rules cssCode.split(;)var ret []for (var i 0; i rules.length; i) {var rule rules[i].replace(/^\s|\s$/, )if (!rule) continueif (rule.match(DataUrlReg)) {rule ; rules[i 1]rule rule.replace(QuotReg, $1)i}ret.push(rule.replace(SpaceReg, ))}return ret
}
现在src下面的文件更改完了我们先去改调用处的vue文件。
第七是路由文件theme-example.vue
templatebasic-containerdiva-button typeprimary主色-primary/a-buttona-button typedanger报错色-danger/a-buttonspan classmy-theme-color测试自定义主题色/spanspan classmy-warning-color测试自定义警告色/spanspan classmy-other-color测试自定义其他颜色/span/divsetting-drawer refsettingDrawer//basic-container
/template
script langts
import BasicContainer from ../../components/layouts/basic-container2.vue
import { Component, Vue } from vue-property-decorator
import SettingDrawer from ../../../packages/setting-drawerComponent({components: {BasicContainer,SettingDrawer},
})
export default class ThemeExample extends Vue {}
/script
style scoped langless
.my-theme-color{color: #1890ff;
}
.my-warning-color{color: #F2A830;
}
.my-other-color{color: #35964f;
}
/style
第八是setting-drawer.vue至于basic-container2.vue就是一个容器文件先不去管
templatediv classsetting-drawerdiv classsetting-drawer-index-contentdiv :style{ marginTop: 24px }h3 classsetting-drawer-index-title切换颜色列表/h3diva-tooltip classsetting-drawer-theme-color-colorBlock v-for(item, index) in colorList :keyindextemplate slottitle{{ item.key }}/templatea-tag :coloritem.color clickchangeColor(item.color,index)a-icon typecheck v-ifitem.color color/a-icona-icon typecheck stylecolor: transparent; v-else/a-icon/a-tag/a-tooltip/div/div/div/div
/templatescript
import { updateTheme, colorList } from ./settingConfigexport default {data () {return {colorList,color: ,}},methods: {changeColor (color, index) {updateTheme({primary: color,danger: this.colorList[index 1] ? this.colorList[index 1].color : this.colorList[0].color,warning: this.colorList[index 2] ? this.colorList[index 2].color : (this.colorList[index 1] ? this.colorList[0].color : this.colorList[1].color),other: this.colorList[index 3] ? this.colorList[index 3].color : (this.colorList[index 2] ? this.colorList[index 2].color : this.colorList[index 1] ? this.colorList[0].color : this.colorList[2].color),})},}
}
/script
第九需要改动的是setting-drawer.vue直接引用的settingConfig.js
import themeColor from ./themeColor.js
const colorList [{key: 薄暮, color: #F5222D},{key: 火山, color: #FA541C},{key: 日暮, color: #FAAD14},{key: 明青, color: #13C2C2},{key: 极光绿, color: #52C41A},{key: 拂晓蓝默认, color: #1890FF},{key: 极客蓝, color: #2F54EB},{key: 酱紫, color: #722ED1},{key: 浅紫, color: #9890Ff}
]const updateTheme (changeColors) {// no-undefthemeColor.changeColor(changeColors).finally(() {})
}export { updateTheme, colorList }
第十需要改动的是settingConfig.js直接引用的themeColor.js
import client from ../../../config/webpack-theme-color-replacer/client
import generate from ant-design/colors/lib/generateexport default {/*** 获取变化的颜色* param color* returns {T[]}*/getAntdSerials (color) {// 淡化即less的tintconst lightens new Array(9).fill().map((t, i) {return client.varyColor.lighten(color, i / 10)})// colorPalette变换得到颜色值// console.log(lightens, lightens)const colorPalettes generate(color)// console.log(colorPalettes, colorPalettes)const rgb client.varyColor.toNum3(color.replace(#, )).join(,)// console.log(rgb, rgb)return lightens.concat(colorPalettes).concat(rgb)},/*** 改变颜色* param changeColors* returns {Promiseunknown|Promiseunknown}*/changeColor (changeColors) {const options {}for (const i in changeColors) {options[i] {newColors: this.getAntdSerials(changeColors[i]),changeUrl (cssUrl) {return /${cssUrl} // while router is not hash mode, it needs absolute path}}}return client.changer.changeColor(options)}
}
这里的关键改动是根据我们的需要组装插件需要的数据源关键代码如下 for (const i in changeColors) {options[i] {newColors: this.getAntdSerials(changeColors[i]),changeUrl (cssUrl) {return /${cssUrl} // while router is not hash mode, it needs absolute path}}}第十一需要改动的是theme-color-changer.js 这里的关键代码是将themeColorConfig按照类型存储和按照类型从LC_THEME_CONFIG和window中取用数据关键代码如下 for (const i in option) {if (!themeColorConfig[i]) {// eslint-disable-next-line no-undefconsole.log(LC_THEME_CONFIG[i], LC_THEME_CONFIG[i])// eslint-disable-next-line no-undefthemeColorConfig[i] win()[LC_THEME_CONFIG[i]]const later retry(i)// 重试直到themeColorConfig加载console.log(later, later)if (later) return later}const { oldColors, newColors, cssUrl, changeUrl } option[i]oldColorsObj[i] oldColors || themeColorConfig[i].colors || []newColorsObj[i] newColors || []const cssUrlValue themeColorConfig[i].url || cssUrlcssUrlObj[i] changeUrl ? changeUrl(cssUrlValue) : cssUrlValue // url可能被changeUrl改变}这里的option就是注册插件时传递的option即代码const createThemeColorReplacerPlugin () new ThemeColorReplacer({ option })。 另外 oldColorsObj newColorsObj cssUrlObj 也需要改为对象形式需要按照键名存储
其他改动后的完整代码如下
const _urlColors {} // {[url]: {id,colors}}
const themeColorConfig {}module.exports {_tryNum: 0,_tryNumObj: {},changeColor: function (option) {const _this thisconst oldColorsObj {}const newColorsObj {}const cssUrlObj {}console.log(wen(), win())// eslint-disable-next-line no-undefconsole.log(LC_THEME_CONFIG, LC_THEME_CONFIG)console.log(option, option)for (const i in option) {if (!themeColorConfig[i]) {// eslint-disable-next-line no-undefconsole.log(LC_THEME_CONFIG[i], LC_THEME_CONFIG[i])// eslint-disable-next-line no-undefthemeColorConfig[i] win()[LC_THEME_CONFIG[i]]const later retry(i)// 重试直到themeColorConfig加载console.log(later, later)if (later) return later}const { oldColors, newColors, cssUrl, changeUrl } option[i]oldColorsObj[i] oldColors || themeColorConfig[i].colors || []newColorsObj[i] newColors || []const cssUrlValue themeColorConfig[i].url || cssUrlcssUrlObj[i] changeUrl ? changeUrl(cssUrlValue) : cssUrlValue // url可能被changeUrl改变}console.log(themeColorConfig, themeColorConfig)return new Promise(function (resolve, reject) {const optionKeys Object.keys(option || {})const isSameArrReturn optionKeys.every(key isSameArr(oldColorsObj[key], newColorsObj[key])) // 判断是不是所有的都相同// console.log(isSameArrReturn, isSameArrReturn)if (isSameArrReturn) {resolve()} else {for (const i in option) {const last _urlColors[cssUrlObj[i]]if (last) {// 之前已替换过oldColorsObj[i] last.colors}if (!isSameArr(oldColorsObj[i], newColorsObj[i])) {setCssText(last, cssUrlObj[i], oldColorsObj[i], newColorsObj[i], i, resolve, reject)}}}})function retry(type) {if (!themeColorConfig[type]) {if (_this._tryNumObj[type] 9) {_this._tryNumObj[type] _this._tryNumObj[type] 1return new Promise(function (resolve, reject) {setTimeout(function () {resolve(_this.changeColor(option))}, 100)})} else {themeColorConfig[type] {}}}}function setCssText(last, url, oldColors, newColors, type, resolve, reject) {// console.log(last, last, ,url, url, ,oldColors, oldColors, ,newColors, newColors, ,type, type,)let elStyle last document.getElementById(last.id)if (elStyle last.colors) {setCssTo(elStyle.innerText)last.colors newColorsresolve()} else {// 第一次替换const id css_ type (new Date())console.log(第一次替换)console.log(id, id)elStyle document.querySelector(option.appendToEl || body).appendChild(document.createElement(style))// console.log(elStyle, elStyle)elStyle.setAttribute(id, id)// console.log(url, url)_this.getCssString(url, function (cssText) {// console.log(cssText, cssText)setCssTo(cssText)_urlColors[url] { id: id, colors: newColors }resolve(cssText)}, reject)}function setCssTo(cssText) {cssText _this.replaceCssText(cssText, oldColors, newColors)elStyle.innerText cssText}}},replaceCssText: function (cssText, oldColors, newColors) {oldColors.forEach(function (color, t) {// #222、#222223、#22222350、222, 255,3 #333、#333334、#33333450、211,133,53、hsl(27, 92.531%, 52.745%)const reg new RegExp(color.replace(/\s/g, ).replace(/,/g, ,\\s*) ([\\da-f]{2})?(\\b|\\)|,|\\s), ig)cssText cssText.replace(reg, newColors[t] $1$2) // 255, 255,3})return cssText},getCssString: function (url, resolve, reject) {// console.log(url, url)const xhr new XMLHttpRequest()xhr.onreadystatechange function () {if (xhr.readyState 4) {if (xhr.status 200) {resolve(xhr.responseText)} else {reject(xhr.status)}}}xhr.onerror function (e) {reject(e)}xhr.ontimeout function (e) {reject(e)}xhr.open(GET, url)xhr.send()},
}
function win() {return typeof window undefined ? global : window
}
function isSameArr(oldColors, newColors) {if (oldColors.length ! newColors.length) {return false}for (let i 0, j oldColors.length; i j; i) {if (oldColors[i] ! newColors[i]) {return false}}return true
}
到这里就结束了vary-color.js不需要改动。然后我们运行后看下效果注意每次改动均需重启项目 颜色批量替换演示我们可以看到页面上成功同时替换了4种颜色。到此这个测试完成。但是我们在页面上实现让用户自定义各种颜色的期望能实现吗 答案是No!! 虽然这不是我们想要的答案但是还是要接受目前的现实。下面讲下原因 1、webpack-theme-color-replacer 这个插件只会根据颜色色号去替换也就是说如果用户自己在主题色和危险色上选了相同的颜色那么出现的结果会是项目上的主题色和危险色都被同时更改并且分不开了除非用户重置。而且如果我们修改css查找正则比如只找css属性名带primary的又会导致没有用ant-design样式的颜色不会被替换 2、其他的比如圆角等的修改估计会波及无辜。因为比如 border-radius: 2px这样的如果按照目前插件的替换逻辑只会替换2px会殃及一大片无辜的样式就算按照规则改成替换border-radius: 2px整个字符也会殃及不少的无辜样式。所以并不现实。
所以好想赶紧升级到vue3啊可以很爽快的使用css变量来实现这些逻辑