自定义主题

1.安装「主题生成工具」

由于主题工具需要依赖于 node-sass,而node-sass版本兼容性并不好,对应 node 版本可能不兼容直接执行npm i element-theme -g所安装的版本,因此需要自行先安装对应 node 版本的node-sass.

对应版本如下

NodeJS Minimum node-sass version Node Module
Node 14 4.14+ 83
Node 13 4.13+ 79
Node 12 4.12+ 72
Node 11 4.10+ 67
Node 10 4.9+ 64
Node 8 4.5.3+ 57

因为我这里的 node 版本是 12.18.1

  1. # 先安装node-sass
  2. set SASS_BINARY_SITE=https://npm.taobao.org/mirrors/node-sass/
  3. npm install node-sass@4.12.0 --save
  4. npm i element-theme -g

特别说明: 若出现 gyp verb check python checking for Python executable "python" in the PATH 错误时。可执行,出现 all done 就算安装完成。

  1. npm install -g node-gyp
  2. npm install --global --production windows-build-tools

2.安装白垩主题

可以从 npm 安装或者从 GitHub 拉取最新代码。

  1. # 从 npm
  2. npm i element-theme-chalk -D
  3. # 从 GitHub
  4. npm i https://github.com/ElementUI/theme-chalk -D

3.新建颜色挑选组件

注意:ORIGINAL_THEME 值不能改变,否则默认按钮颜色不会改变。

代码如下:

  1. <template>
  2. <el-tooltip effect="dark" content="换肤" placement="bottom">
  3. <el-color-picker class="theme-picker" popper-class="theme-picker-dropdown" v-model="theme" :size="size"> </el-color-picker>
  4. </el-tooltip>
  5. </template>
  6. <script>
  7. const version = require('element-ui/package.json').version // element-ui version from node_modules
  8. const ORIGINAL_THEME = '#409EFF' // default color
  9. export default {
  10. name: 'ThemePicker',
  11. props: {
  12. default: {
  13. // 初始化主题,可由外部传入
  14. type: String,
  15. default: null,
  16. },
  17. size: {
  18. // 初始化主题,可由外部传入
  19. type: String,
  20. default: 'small',
  21. },
  22. },
  23. data() {
  24. return {
  25. chalk: '', // content of theme-chalk css
  26. theme: ORIGINAL_THEME,
  27. showSuccess: true, // 是否弹出换肤成功消息
  28. }
  29. },
  30. mounted() {
  31. if (this.default != null) {
  32. this.theme = this.default
  33. this.$emit('onThemeChange', this.theme)
  34. this.showSuccess = false
  35. }
  36. },
  37. watch: {
  38. theme(val, oldVal) {
  39. if (typeof val !== 'string') return
  40. const themeCluster = this.getThemeCluster(val.replace('#', ''))
  41. const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
  42. const getHandler = (variable, id) => {
  43. return () => {
  44. const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
  45. const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
  46. let styleTag = document.getElementById(id)
  47. if (!styleTag) {
  48. styleTag = document.createElement('style')
  49. styleTag.setAttribute('id', id)
  50. document.head.appendChild(styleTag)
  51. }
  52. styleTag.innerText = newStyle
  53. }
  54. }
  55. const chalkHandler = getHandler('chalk', 'chalk-style')
  56. if (!this.chalk) {
  57. const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
  58. this.getCSSString(url, chalkHandler, 'chalk')
  59. } else {
  60. chalkHandler()
  61. }
  62. const styles = [].slice.call(document.querySelectorAll('style')).filter((style) => {
  63. const text = style.innerText
  64. return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
  65. })
  66. styles.forEach((style) => {
  67. const { innerText } = style
  68. if (typeof innerText !== 'string') return
  69. style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
  70. })
  71. // 响应外部操作
  72. this.$emit('onThemeChange', val)
  73. if (this.showSuccess) {
  74. this.$message({
  75. message: '换肤成功',
  76. type: 'success',
  77. })
  78. } else {
  79. this.showSuccess = true
  80. }
  81. },
  82. },
  83. methods: {
  84. updateStyle(style, oldCluster, newCluster) {
  85. let newStyle = style
  86. oldCluster.forEach((color, index) => {
  87. newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
  88. })
  89. return newStyle
  90. },
  91. getCSSString(url, callback, variable) {
  92. const xhr = new XMLHttpRequest()
  93. xhr.onreadystatechange = () => {
  94. if (xhr.readyState === 4 && xhr.status === 200) {
  95. this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
  96. callback()
  97. }
  98. }
  99. xhr.open('GET', url)
  100. xhr.send()
  101. },
  102. getThemeCluster(theme) {
  103. const tintColor = (color, tint) => {
  104. let red = parseInt(color.slice(0, 2), 16)
  105. let green = parseInt(color.slice(2, 4), 16)
  106. let blue = parseInt(color.slice(4, 6), 16)
  107. if (tint === 0) {
  108. // when primary color is in its rgb space
  109. return [red, green, blue].join(',')
  110. } else {
  111. red += Math.round(tint * (255 - red))
  112. green += Math.round(tint * (255 - green))
  113. blue += Math.round(tint * (255 - blue))
  114. red = red.toString(16)
  115. green = green.toString(16)
  116. blue = blue.toString(16)
  117. return `#${red}${green}${blue}`
  118. }
  119. }
  120. const shadeColor = (color, shade) => {
  121. let red = parseInt(color.slice(0, 2), 16)
  122. let green = parseInt(color.slice(2, 4), 16)
  123. let blue = parseInt(color.slice(4, 6), 16)
  124. red = Math.round((1 - shade) * red)
  125. green = Math.round((1 - shade) * green)
  126. blue = Math.round((1 - shade) * blue)
  127. red = red.toString(16)
  128. green = green.toString(16)
  129. blue = blue.toString(16)
  130. return `#${red}${green}${blue}`
  131. }
  132. const clusters = [theme]
  133. for (let i = 0; i <= 9; i++) {
  134. clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
  135. }
  136. clusters.push(shadeColor(theme, 0.1))
  137. return clusters
  138. },
  139. },
  140. }
  141. </script>
  142. <style>
  143. .theme-picker .el-color-picker__trigger {
  144. vertical-align: middle;
  145. }
  146. .theme-picker-dropdown .el-color-dropdown__link-btn {
  147. display: none;
  148. }
  149. </style>

然后在 vuex 对应 vue 模块中,添加颜色管理的状态值。

在 头部添加 颜色选择的组件,供全局选择,代码如下:

  1. import ThemePicker from '@/components/ThemePicker'
  2. //引入组件
  3. components: { ThemePicker },
  4. //使用
  5. <theme-picker
  6. :default="themeColor"
  7. @onThemeChange="onThemeChange">
  8. </theme-picker>
  9. methods: {
  10. // 切换主题方法
  11. onThemeChange (themeColor)
  12. {
  13. this.$store.commit("setThemeColor", themeColor);
  14. }
  15. } //将颜色用状态管理器管理。

在每次颜色改变时,设置到 state.themeColor 上,在各个需要改变皮肤的地方,从 state 中取出来,然后赋值进去。

原文地址:http://book.levy.net.cn/doc/frontend/uiframe/custom_theme.html

Vue管理系统前端系列五自定义主题的更多相关文章

  1. Vue管理系统前端系列一vue-cli4.x 初始化项目

    目录 项目介绍 技术基础 开发环境 安装工具 快速原型开发 创建项目 配置相关说明 目录结构 项目介绍 lion-ui 是一个基于 RBAC 的管理系统前端项目,采用 vue 和 element-ui ...

  2. Vue管理系统前端系列三登录页和首页及`vuex`管理登录状态

    目录 登录页面设计 vuex 对应 用户模块 丰富界面 首页相关代码 登录页面设计 该节记录了登录界面的设计,以及 vuex 的简单实用,然后将首页简单搭建完成. 先看最终效果图 先在 views 文 ...

  3. Vue管理系统前端系列六动态路由-权限管理实现

    目录 为什么要使用动态路由? 主流的两种实现方式 前端控制 后端控制 后端控制路由 实现 添加菜单接口 及 菜单状态管理 根据得到的菜单生成动态路由 根据 vuex 中的暂存的菜单生成侧边菜单栏 退出 ...

  4. Vue管理系统前端系列二相关工具引入及封装

    目录 sass-loader/vuex 等的引入说明 引入 element 引入 axios 1.基本使用 2.封装使用 2.1 开发环境配置请求地址 2.2 配置代理 2.3 添加接口相关文件 sa ...

  5. Vue管理系统前端系列四组件拆分封装

    目录 组件封装 首页布局拆分后结构 拆分后代码 状态管理中添加 app 模块 组件封装 在上一篇记录中,首页中有太多的代码,为了避免代码的臃肿,需要对主要的功能模块拆分,来让代码看起来更简洁,且能进行 ...

  6. Vue + Element UI 实现权限管理系统 前端篇(八):管理应用状态

    使用 Vuex 管理应用状态 1. 引入背景 像先前我们是有导航菜单栏收缩和展开功能的,但是因为组件封装的原因,隐藏按钮在头部组件,而导航菜单在导航菜单组件,这样就涉及到了组件收缩状态的共享问题.收缩 ...

  7. vue 快速入门 系列 —— vue-cli 下

    其他章节请看: vue 快速入门 系列 Vue CLI 4.x 下 在 vue loader 一文中我们已经学会从零搭建一个简单的,用于单文件组件开发的脚手架:本篇,我们将全面学习 vue-cli 这 ...

  8. [后端人员耍前端系列]AngularJs篇:30分钟快速掌握AngularJs

    一.前言 对于前端系列,自然少不了AngularJs的介绍了.在前面文章中,我们介绍了如何使用KnockoutJs来打造一个单页面程序,后面一篇文章将介绍如何使用AngularJs的开发一个单页面应用 ...

  9. vue.js学习系列-第一篇

    VUE系列一 简介    vue是一个兴起的前端js库,是一个精简的MVVM.从技术角度讲,Vue.js专注于 MVVM 模型的 ViewModel 层.它通过双向数据绑定把 View 层和 Mode ...

随机推荐

  1. JVM详解之:汇编角度理解本地变量的生命周期

    目录 简介 本地变量的生命周期 举例说明 优化的原因 总结 简介 java方法中定义的变量,它的生命周期是什么样的呢?是不是一定要等到方法结束,这个创建的对象才会被回收呢? 带着这个问题我们来看一下今 ...

  2. Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform!

    原文链接:https://blog.csdn.net/u012700515/article/details/56009429 Maven 打包时有标题中警告,需要在pom.xml文件中添加 <p ...

  3. Python List list()方法

    描述 list() 方法用于将元组转换为列表.高佣联盟 www.cgewang.com 注:元组与列表是非常类似的,区别在于元组的元素值不能修改,元组是放在括号中,列表是放于方括号中. 语法 list ...

  4. PHP serialize() 函数

    serialize() 函数用于序列化对象或数组,并返回一个字符串.高佣联盟 www.cgewang.com serialize() 函数序列化对象后,可以很方便的将它传递给其他需要它的地方,且其类型 ...

  5. PHP str_split() 函数

    实例 把字符串 "Hello" 分割到数组中: <?php print_r(str_split("Hello")); ?>高佣联盟 www.cgew ...

  6. zabbix配置自定义监控

    目录 zabbix配置自定义监控项---进程监控 1. 编写获取进程状态的脚本 2. 修改配置文件,添加自定义key 3. 配置监控项 4. 添加触发器 5. 媒介和动作 6. 触发并验证 zabbi ...

  7. 埋在MySQL数据库应用中的17个关键问题!

    作者:扎瓦陈序元 来源:https://blog.csdn.net/weixin_42882439 MySQL的使用非常普遍,跟MySQL有关的话题也非常多,如性能优化.高可用性.强一致性.安全.备份 ...

  8. 郭超:阿里云Cassandra背后的故事

    大家好,我是阿里云数据库产品事业部的玄陵,真名郭超. ​ 本次的分享大概分三个部分:Cassandra云数据库简介.Cassandra云数据库特性以及Q&A. ​ 我们先了解一下Cassand ...

  9. WebService简单Demo

    看了网上好多关于webservice的例子,基本上对初学者来说都是模棱两可云里雾里,现在,我将网上关于webservice的讲解提炼出来,通过一个最简单使用并且方便的例子,告诉大家什么是webserv ...

  10. c语言学习笔记之typedef

    这是我觉得这个博主总结的很好转载过来的 原地址:https://blog.csdn.net/weixin_41632560/article/details/80747640 C语言语法简单,但内涵却博 ...