Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.7k views
in Technique[技术] by (71.8m points)

elementui主题, 如何动态设置scss变量的值?目的还是动态修改elementui框架的主题颜色

如图官方的修改方法

image

我的项目中使用了elementui作为框架,同时使用了scss。
有没有办法动态更改这个变量的值来设置不同的主题?

之前的思路是动态引入不同的主题

// 不同的主题文件,他们的内容只有一个就是设置
// $--color-primary: theme1;
// $--color-primary: theme2;
// $--color-primary: theme3;
// 如果使用var变量来会导致构建失败
// $--color-primary: var(--primary, red)


// 通过接口获取到主题
let theme = getTheme()
import(`./${theme}.scss`)

这样存在一个问题,就是实际构建的时候,所有定义的主题都会被编译。就算我没有动态引入也会被编译,导致主题之间互相覆盖。
所以现在想只用一个scss文件来定义变量,但是这个变量的值不是固定的,有没有办法处理呢?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

经过不断的尝试和搜索,我发现所有实现方式最终还是和elementUI切换主题源码的实现方式基本一致,即手动替换掉框架原来的颜色。

源码如下:

ementui切换主题源码
如果项目配置的webpack在4.0以上的用户也可以查看这篇文章,对框架的处理原理也是类似的
https://ostack.cn/a/11...

最终我自己的实现也类似,代码如下,供参考:

import color from 'css-color-function'
// 这里是elementui对应的颜色公式,和elementui源码中的formula一致
import elementFormula from './elementFormula'

// element_ui默认的主题色
const ORIGINAL_THEME = '#409EFF'
const version = require('element-ui/package.json').version // 版本号
// 所有element_ui的默认样式
let themeChalk = null

// 获取默认element_ui颜色转换后的数组
function getThemeColorArray (theme) {
  let colors = [theme.replace('#', '')]
  Object.keys(elementFormula).forEach(key => {
    const value = elementFormula[key].replace(/primary/g, theme)
    colors.push(color.convert(value).replace('#', ''))
  })
  return colors
}

/**
 * 替换掉所有的旧颜色
 * @param {Array} oldStyleArray 老的element_ui颜色数组,使用element_ui默认的主题色生成
 * @param {Array} newStyleArray 新颜色数组,通过 getThemeColorArray 方法转换颜色生成
 * */
function updateStyle (oldStyleArray, newStyleArray) {
  oldStyleArray.forEach((color, index) => {
    themeChalk = themeChalk.replace(new RegExp(color, 'ig'), newStyleArray[index])
  })
  return themeChalk
}

function getCSSString (url, callback) {
  const xhr = new XMLHttpRequest()
  xhr.onreadystatechange = () => {
    if (xhr.readyState === 4 && xhr.status === 200) {
      themeChalk = xhr.responseText.replace(/@font-face{[^}]+}/, '')
      callback()
    }
  }
  xhr.open('GET', url)
  xhr.send()
}

// 转换主题颜色
export function changeThemeColor (primary) {
  if (typeof primary !== 'string') return
  // 生成新的对应颜色数组
  const themeStyleArray = getThemeColorArray(primary)
  const getHandler = (id) => {
    return () => {
      const originalStyleArray = getThemeColorArray(ORIGINAL_THEME)
      const newStyle = updateStyle(
        originalStyleArray,
        themeStyleArray
      )

      let styleTag = document.getElementById(id)
      if (!styleTag) {
        styleTag = document.createElement('style')
        styleTag.setAttribute('id', id)
        document.head.appendChild(styleTag)
      }
      styleTag.innerText = newStyle
    }
  }
  const themeHandler = getHandler('redcat-theme-style')

  // 第一次从cdn获取对应的样式文件
  if (!themeChalk) {
    const url = `//unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
    getCSSString(url, themeHandler)
  } else {
    themeHandler()
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...