美文网首页
element ui+vue2.0实现换肤并且自身写的颜色也可以

element ui+vue2.0实现换肤并且自身写的颜色也可以

作者: 码农一名__ | 来源:发表于2021-04-27 19:43 被阅读0次

问题:本地环境换肤可以,但是打包后发现自己写的主题色值#409eff,并没有被替换成功,只有element ui自身的主题色替换了

主要代码如下:

//watch监听主题色变化
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()
        /**++++++++++++++++++++++++++++++++++++++++++++++++ */
        //为解决生产环境中切换主题色失败
        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 的内容
                if (
                  new RegExp(oldVal, 'i').test(data) && // 判断是否需要换肤
                  !/Chalk Variables/.test(data) // 判断是否是 element-ui 的 css 前面已经进行处理了这里忽略
                ) {
                  item.remove() // 移出 link
                  const style = document.createElement('style') // 创建 style
                  style.innerText = data // 把 link 的内容添加到 style 标签中
                  // 更新背景图会导致路径错误,忽略更新。
                  style.innerText = data.replace(
                    /url\(..\/..\/static/g,
                    'url(static'
                  )
                  style.isAdd = true // 为后面判断是否是 link 生成的style,方便标识加入到头部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转换的style
        if (style.isAdd) {
          // 如果是通过 link 创建的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
    },

为了解决上面的问题:我主要加的代码在加注释那一块,上面的问题出现的原因在于,
1、打包后的css为link形式,而我的换肤时主要筛选的是style样式,然后进行替换。因此我判断是否是生产环境并且是第一次进来,然后将link样式转为style,通过axios请求获得link下的内容,成功后移除了link,创建style,并把获得的内容赋予给style

item.remove() // 移出 link
const style = document.createElement('style') // 创建 style
style.innerText = data // 把 link 的内容添加到 style 标签中

2、然后我打了一个包,发现我的自己写的颜色值#409eff都被换成我想要的主题色,但是另一个问题来了,我的背景图片加载失败了。我去f12看了下,我的图片路径变成了../../static。于是我只能在转换style的时候手动的改下路径

// 更新背景图会导致路径错误,忽略更新。
style.innerText = data.replace(/url\(..\/..\/static/g,'url(static')

3、再次打了一个包,终于都可以正常显示了,真的是坎坷。

相关文章

  • element ui+vue2.0实现换肤并且自身写的颜色也可以

    问题:本地环境换肤可以,但是打包后发现自己写的主题色值#409eff,并没有被替换成功,只有element ui自...

  • iOS app换肤

    app 换肤 关于app换肤的几种方式 本地换肤 本地换肤,是通过包里面自身已经拥有的图片和颜色配置,对视图以及各...

  • 换肤

    换肤 1. 换肤的应用场景? 2. 换肤的实现方案 方案1 1. 将图片以及颜色按照主题命名,使用虚拟文件夹, 直...

  • vue element-ui 实现换肤

    1.自定义主题 自定义几种固定主题,目前是公司项目中最常用的方式 安装 element-theme 安装 them...

  • Android 简单换肤效果的实现

    android 换肤无非就是改变字体的颜色,控件的背景等显示效果。 下面看看SkinActivity的实现: 先上...

  • 动态修改css中:root定义的变量-换肤、主题色

    前端中有用到需要设置主题颜色,根据用户喜欢实现换肤的可以使用css中:root定义变量的方式,或者使用动态切换引入...

  • ELEMENT UI换肤

    目前element-ui版本已到2.6.3 但是官方提供的element-theme针对的2.0.1的换肤导致 e...

  • element-ui 组件库 button 源码分析

    前言 团队要根据新的 UI 规范实现一个组件库,button 组件规范要支持多种主题换肤,字体颜色、背景颜色、边框...

  • 换肤框架

    序言 现在说是换肤框架还有点夸大其词,因为目前只实现了颜色的替换,目前网上已有的换肤框架我都研究过,主要感觉给每个...

  • EventTarget对象

    EventTarget是一个由可以接受事件的对象实现的接口.并且可以为它们创建监听器.element, docum...

网友评论

      本文标题:element ui+vue2.0实现换肤并且自身写的颜色也可以

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