自定义修改element主题

实现自定义element主题

  • 封装组件ThemePicker.vue
<template>
  <el-color-picker
    class="theme-picker"
    popper-class="theme-picker-dropdown"
    v-model="theme"
    :disabled="disabled"
    :predefine="predefine"
    :size="size">
  </el-color-picker>
</template>

<script>
  const version = require('element-ui/package.json').version // element-ui version from node_modules
  const ORIGINAL_THEME = '#409EFF' // default color
  export default {
    name: 'ThemePicker',
    props: {
      // 是否禁用
      disabled: {
        type: Boolean
      },
      // 预定义颜色 ()
      predefine: {
        type: Array
      },
      // 默认初始化主题
      default: {
        type: String,
        default: ""+localStorage.getItem("tremePackers")+""
      },
      // 尺寸
      size: {
        type: String,
        default: 'small'
      }
    },
    data() {
      return {
        chalk: '', // content of theme-chalk css
        theme: ORIGINAL_THEME,
        showSuccess: true, // 是否弹出换肤成功消息
      }
    },
    mounted() {
      if(this.default != null) {
        this.theme = this.default
        // this.$emit('onThemeChange', this.theme)
        this.showSuccess = false
      }
    },
    watch: {
      theme(val, oldVal) {
        if (typeof val !== 'string') return
        const themeCluster = this.getThemeCluster(val.replace('#', ''))
        const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
        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
          }
        }
        // 替换主题
        const chalkHandler = getHandler('chalk', 'chalk-style')

        if (!this.chalk) {
          const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
          this.getCSSString(url, chalkHandler, 'chalk')
        } else {
          // 这里可以写自己想要的逻辑(如: 改变布局等情况)
          // console.log(val)
          chalkHandler()
        }

        const styles = [].slice.call(document.querySelectorAll('style'))
          .filter(style => {
            const text = style.innerText
            return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
          })
        styles.forEach(style => {
          const { innerText } = style
          if (typeof innerText !== 'string') return
          style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
        })

        // 响应外部操作
        this.$emit('onThemeChange', val)
        //存入localStorage
        localStorage.setItem('tremePackers',val);
        if(this.showSuccess) {
          this.$message({
            message: '换肤成功',
            type: 'success'
          })
        } else {
          this.showSuccess = true
        }
      }
    },
    methods: {
      updateStyle(style, oldCluster, newCluster) {
        let newStyle = style
        oldCluster.forEach((color, index) => {
          newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
        })
        return newStyle
      },

      getCSSString(url, callback, variable) {
        const xhr = new XMLHttpRequest()
        xhr.onreadystatechange = () => {
          if (xhr.readyState === 4 && xhr.status === 200) {
            this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
            callback()
          }
        }
        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
      }
    }
  }
</script>

<style>
  .theme-picker .el-color-picker__trigger {
    vertical-align: middle;
  }

  .theme-picker-dropdown .el-color-dropdown__link-btn {
    display: none;
  }
</style>


  • 引入组件调用
<template>
	<div>
		<theme-picker></theme-picker>
	</div>
</template>
<script>
import themePicker from "@/components/ThemePicker.vue"
export default {
  components: {
    themePicker
  },
}
</script>

  • 组件参数
参数说明类型默认必填
default默认颜色(不保存颜色)String--
size颜色选择器大小Stringmedium / small / minismall
disabled是否禁用Booleantrue/falsefalse
predefine预定义颜色Array[]-
  • event事件
事件名说明参数
onThemeChange当颜色值变化时触发(第一次进来也会触发)value
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Element Plus提供了多种方式来自定义颜色。其中一种方式是在组件中引入自定义的样式文件。你可以在组件的`<style>`标签中使用`@import`语句来引入自定义的样式文件,然后在该文件中设置自定义的颜色变量。例如,在组件中引入自定义样式文件`custom-element.scss`,并在该文件中设置`--el-color-primary`变量为你想要的颜色值。这样,在该组件中就可以使用自定义的颜色主题了。\[1\] 另一种方式是在根组件`App.vue`的`onMounted`钩子中执行自定义颜色主题的设置。你可以使用`setVarStyle`函数来设置Element Plus的颜色变量,例如设置`--el-color-primary`为你想要的颜色值。这样,在整个应用中都会应用这个自定义的颜色主题。\[2\] 还有一种方式是在`index.scss`文件中使用`@forward`语句导入Element Plus的变量,并在该文件中设置自定义的颜色主题。你可以使用`$colors`变量来设置不同状态下的颜色值,例如设置`"primary"`状态的颜色为你想要的颜色值。这样,在整个应用中都会应用这个自定义的颜色主题。\[3\] #### 引用[.reference_title] - *1* *2* *3* [ElementPlus 修改主题色和暗黑模式切换](https://blog.csdn.net/gsy445566778899/article/details/130843599)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值