問題:本地環(huán)境換膚可以玫氢,但是打包后發(fā)現(xiàn)自己寫的主題色值#409eff阳掐,并沒有被替換成功紊婉,只有element ui自身的主題色替換了
主要代碼如下:
//watch監(jiān)聽主題色變化
theme: {
async handler(val) {
const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
if (typeof val !== 'string') return
const themeCluster = this.getThemeCluster(val.replace('#', ''))
const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
const $message = this.$message({
message: '主題色切換中...',
customClass: 'theme-message',
type: 'success',
duration: 0,
iconClass: 'el-icon-loading',
})
const getHandler = (variable, id) => {
return () => {
const originalCluster = this.getThemeCluster(
ORIGINAL_THEME.replace('#', '')
)
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
}
}
if (!this.chalk) {
const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
await this.getCSSString(url, 'chalk')
}
const chalkHandler = getHandler('chalk', 'chalk-style')
chalkHandler()
/**++++++++++++++++++++++++++++++++++++++++++++++++ */
//為解決生產(chǎn)環(huán)境中切換主題色失敗
if (!this.flag && process.env.NODE_ENV === 'production') {
//判斷是否是第一次打開頁面
this.flag = true
;[].slice
.call(document.querySelectorAll('link')) //獲取所有的link鏈接
.forEach(async (item) => {
if (item.rel === 'stylesheet' || item.as === 'style') {
//判斷是否是 css
const { data } = await axios.get(item.href) // 重新獲取到 css 的內(nèi)容
if (
new RegExp(oldVal, 'i').test(data) && // 判斷是否需要換膚
!/Chalk Variables/.test(data) // 判斷是否是 element-ui 的 css 前面已經(jīng)進(jìn)行處理了這里忽略
) {
item.remove() // 移出 link
const style = document.createElement('style') // 創(chuàng)建 style
style.innerText = data // 把 link 的內(nèi)容添加到 style 標(biāo)簽中
// 更新背景圖會(huì)導(dǎo)致路徑錯(cuò)誤会油,忽略更新烙无。
style.innerText = data.replace(
/url\(..\/..\/static/g,
'url(static'
)
style.isAdd = true // 為后面判斷是否是 link 生成的style录豺,方便標(biāo)識(shí)加入到頭部head中
styles.push(style)
this.stylesRender(styles, originalCluster, themeCluster) // 樣式渲染
}
}
})
}
/**++++++++++++++++++++++++++++++++++++++++++++++++ */
// 篩選需要修改的style
const styles = [].slice
.call(document.querySelectorAll('style'))
.filter((style) => {
const text = style.innerText
return (
new RegExp(oldVal, 'i').test(text) &&
!/Chalk Variables/.test(text)
)
})
this.styleRender(styles, originalCluster, themeCluster)
this.$emit('change', val)
$message.close()
},
immediate: true,
},
// 遍歷修改所有需修改的style
styleRender(styles, originalCluster, themeCluster) {
styles.forEach((style) => {
const { innerText } = style
if (typeof innerText !== 'string') return
style.innerText = this.updateStyle(
innerText,
originalCluster,
themeCluster
)
//打包后的link轉(zhuǎn)換的style
if (style.isAdd) {
// 如果是通過 link 創(chuàng)建的style 就添加到head中
style.isAdd = false
document.head.appendChild(style)
}
})
},
//更新 <style>
updateStyle(style, oldCluster, newCluster) {
let newStyle = style
oldCluster.forEach((color, index) => {
newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
})
return newStyle
},
//修改lin引入的css
getCSSString(url, variable) {
return new Promise((resolve) => {
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
resolve()
}
}
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) {
// when primary color is in its rgb space
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
},
為了解決上面的問題:我主要加的代碼在加注釋那一塊跷车,上面的問題出現(xiàn)的原因在于链方,
1牵现、打包后的css為link形式铐懊,而我的換膚時(shí)主要篩選的是style樣式,然后進(jìn)行替換瞎疼。因此我判斷是否是生產(chǎn)環(huán)境并且是第一次進(jìn)來科乎,然后將link樣式轉(zhuǎn)為style,通過axios請(qǐng)求獲得link下的內(nèi)容,成功后移除了link贼急,創(chuàng)建style茅茂,并把獲得的內(nèi)容賦予給style
item.remove() // 移出 link
const style = document.createElement('style') // 創(chuàng)建 style
style.innerText = data // 把 link 的內(nèi)容添加到 style 標(biāo)簽中
2捏萍、然后我打了一個(gè)包,發(fā)現(xiàn)我的自己寫的顏色值#409eff都被換成我想要的主題色空闲,但是另一個(gè)問題來了令杈,我的背景圖片加載失敗了。我去f12看了下碴倾,我的圖片路徑變成了../../static逗噩。于是我只能在轉(zhuǎn)換style的時(shí)候手動(dòng)的改下路徑
// 更新背景圖會(huì)導(dǎo)致路徑錯(cuò)誤,忽略更新跌榔。
style.innerText = data.replace(/url\(..\/..\/static/g,'url(static')
3异雁、再次打了一個(gè)包,終于都可以正常顯示了僧须,真的是坎坷纲刀。