基于element-ui 动态换肤的代码详解

1、在安装好element-ui@2.x 以后,首先安装sass-loader

  1. npm i sass-loader node-sass -D

2、安装element-theme

  1. npm i element-theme -D

3、安装theme-chalk

  1. npm i element-theme-chalk -D
  2. # or from github
  3. npm i https://github.com/ElementUI/theme-chalk -D

4、初始化变量文件

  1. et -i // 默认的文件是element-variables.scss,也可以自定义文件名 et --init [file path]

安装成功以后,在项目里会自动生成一个element-variables.scss 文件,如下图:

里面定义的是所有的颜色变量

当然,这一步也有可能失败,命令行提示找不到et 这个命令。这个时候需要按照步骤一,重新装一下sass-loader

5、修改变量

直接编辑 element-variables.scss 文件,例如修改主题色为红色

6、编译主题

保存文件后,到命令行里执行 et 编译主题,如果你想启用 watch 模式,实时编译主题,增加 -w 参数;如果你在初始化时指定了自定义变量文件,则需要增加 -c 参数,并带上你的变量文件名

此时,项目中会自动生成一个theme文件夹,里面是编译后所有的字体文件和样式文件

7、引入自定义主题

默认情况下编译的主题目录是放在 ./theme 下,你可以通过 -o 参数指定打包目录。像引入默认主题一样,在代码里直接引用 theme/index.css 文件即可。

  1. import '../theme/index.css'
  2. import ElementUI from 'element-ui'
  3. import Vue from 'vue'
  4.  
  5. Vue.use(ElementUI)

启动项目,会发现原来默认的蓝色会变成红色

官网提供的这种方法仅适用于一次性的更改全局主题颜色,如果想实现官网2.0版本右上角,使用 ColorPicker 颜色选择器 动态换肤。那么建议参考vue-element-admin,作者的 《手摸手,带你用vue撸后台》系列文章非常精彩

  1. ThemePicker.vue
  2. <template>
  3. <el-tooltip effect="dark" content="theme" placement="bottom">
  4. <el-color-picker
  5. v-model="theme"
  6. class="theme-picker"
  7. size="small"
  8. popper-class="theme-picker-dropdown"/>
  9. </el-tooltip>
  10. </template>
  11. <script>
  12. const version = require('element-ui/package.json').version // element-ui version from node_modules
  13. const ORIGINAL_THEME = '#409EFF' // default color
  14. export default {
  15. data() {
  16. return {
  17. chalk: '', // content of theme-chalk css
  18. theme: ORIGINAL_THEME
  19. }
  20. },
  21. watch: {
  22. theme(val, oldVal) {
  23. if (typeof val !== 'string') return
  24. const themeCluster = this.getThemeCluster(val.replace('#', ''))
  25. const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
  26. console.log(themeCluster, originalCluster)
  27. const getHandler = (variable, id) => {
  28. return () => {
  29. const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
  30. const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
  31. let styleTag = document.getElementById(id)
  32. if (!styleTag) {
  33. styleTag = document.createElement('style')
  34. styleTag.setAttribute('id', id)
  35. document.head.appendChild(styleTag)
  36. }
  37. styleTag.innerText = newStyle
  38. }
  39. }
  40. const chalkHandler = getHandler('chalk', 'chalk-style')
  41. if (!this.chalk) {
  42. const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
  43. this.getCSSString(url, chalkHandler, 'chalk')
  44. } else {
  45. chalkHandler()
  46. const styles = [].slice.call(document.querySelectorAll('style'))
  47. .filter(style => {
  48. const text = style.innerText
  49. return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
  50. })
  51. styles.forEach(style => {
  52. const { innerText } = style
  53. if (typeof innerText !== 'string') return
  54. style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
  55. })
  56. this.$message({
  57. message: '换肤成功',
  58. type: 'success'
  59. methods: {
  60. updateStyle(style, oldCluster, newCluster) {
  61. let newStyle = style
  62. oldCluster.forEach((color, index) => {
  63. newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
  64. return newStyle
  65. },
  66. getCSSString(url, callback, variable) {
  67. const xhr = new XMLHttpRequest()
  68. xhr.onreadystatechange = () => {
  69. if (xhr.readyState === 4 && xhr.status === 200) {
  70. this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
  71. callback()
  72. xhr.open('GET', url)
  73. xhr.send()
  74. getThemeCluster(theme) {
  75. const tintColor = (color, tint) => {
  76. let red = parseInt(color.slice(0, 2), 16)
  77. let green = parseInt(color.slice(2, 4), 16)
  78. let blue = parseInt(color.slice(4, 6), 16)
  79. if (tint === 0) { // when primary color is in its rgb space
  80. return [red, green, blue].join(',')
  81. } else {
  82. red += Math.round(tint * (255 - red))
  83. green += Math.round(tint * (255 - green))
  84. blue += Math.round(tint * (255 - blue))
  85. red = red.toString(16)
  86. green = green.toString(16)
  87. blue = blue.toString(16)
  88. return `#${red}${green}${blue}`
  89. const shadeColor = (color, shade) => {
  90. red = Math.round((1 - shade) * red)
  91. green = Math.round((1 - shade) * green)
  92. blue = Math.round((1 - shade) * blue)
  93. red = red.toString(16)
  94. green = green.toString(16)
  95. blue = blue.toString(16)
  96. return `#${red}${green}${blue}`
  97. const clusters = [theme]
  98. for (let i = 0; i <= 9; i++) {
  99. clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
  100. clusters.push(shadeColor(theme, 0.1))
  101. return clusters
  102. }
  103. }
  104. </script>
  1. Navbar.vue
  2. <template>
  3. <el-menu class="navbar" mode="horizontal">
  4. <hamburger
  5. class="hamburger-container"
  6. :toggleClick="toggleSideBar"
  7. :isActive="!sidebar.opened">
  8. </hamburger>
  9. <div class="right-menu">
  10. <screenfull class="screenfull"></screenfull>
  11. <div class="lang">
  12. <el-dropdown>
  13. <i class="iconfont icon-language4"></i>
  14. <el-dropdown-menu slot="dropdown">
  15. <el-dropdown-item @click.native="toggleLang('zh')" :disabled="$i18n.locale == 'zh'">中文</el-dropdown-item>
  16. <el-dropdown-item @click.native="toggleLang('en')" :disabled="$i18n.locale == 'en'">English</el-dropdown-item>
  17. </el-dropdown-menu>
  18. </el-dropdown>
  19. </div>
  20. <theme-picker></theme-picker>
  21. </div>
  22. </el-menu>
  23. </template>

以上demo代码地址:https://github.com/frwupeng517/element-admin

Element-UI 官方文档地址:http://element-cn.eleme.io/#/zh-CN/component/custom-theme

PanJiachen Git地址:https://github.com/PanJiaChen/vue-element-admin

到此这篇关于element-ui 动态换肤的文章就介绍到这了,更多相关element-ui 动态换肤内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

posted @ 2022-08-22 16:12  飞雪飘鸿  阅读(878)  评论(0编辑  收藏  举报
https://damo.alibaba.com/ https://tianchi.aliyun.com/course?spm=5176.21206777.J_3941670930.5.87dc17c9BZNvLL