自定义主题

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

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

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

npm install -g node-gyp
npm install --global --production windows-build-tools

2.安装白垩主题

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

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

3.新建颜色挑选组件

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

代码如下:

<template>
<el-tooltip effect="dark" content="换肤" placement="bottom">
<el-color-picker class="theme-picker" popper-class="theme-picker-dropdown" v-model="theme" :size="size"> </el-color-picker>
</el-tooltip>
</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: {
default: {
// 初始化主题,可由外部传入
type: String,
default: null,
},
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 {
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)
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>

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

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

import ThemePicker from '@/components/ThemePicker'
//引入组件
components: { ThemePicker }, //使用
<theme-picker
:default="themeColor"
@onThemeChange="onThemeChange">
</theme-picker> methods: {
// 切换主题方法
onThemeChange (themeColor)
{
this.$store.commit("setThemeColor", themeColor);
}
} //将颜色用状态管理器管理。

在每次颜色改变时,设置到 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. 来自马铁大神的Spark10年回忆录

    本篇分享来自Martei在Spark AI Submit 2020的开场分享. 马铁是谁 什么!你不知道马铁是谁?Martei Zaharia(说实话,不知道谁给起的中文名字叫马铁,跟着叫就是了),现 ...

  2. jmeter正则表达式,萌新入门篇

    @@@@@@@@@@@@ 透过现象看本质 jmeter中正则表达式对我们来说,就是一个工具,他可以帮助我们做的事就是从一堆数据中截取出我们想要的字段,比如从setcookie:DERF12456DAS ...

  3. ionic 侧边栏实例

    侧边栏的使用范例: <body > <ion-side-menus> <!-- 中间内容 --> <ion-side-menu-content ng-cont ...

  4. try{}catch的隐藏(如何优雅的实现异常块)

    在项目中,我们会遇到异常处理,对于运行时异常,需要我们自己判断处理.对于受检异常,需要我们主动处理. 但是繁琐的try{}caht嵌套在代码里,看着很不舒服,这里我们不讨论性能,就代码来讲,来看看如何 ...

  5. Springboot+Mybatis+Clickhouse+jsp 搭建单体应用项目(一)

    一.服务器安装clickhouse服务 参阅 :https://www.cnblogs.com/liuyangfirst/p/13379064.html 二.连接数据库 成功 三.新建库 CREATE ...

  6. Python os.chown() 方法

    概述 os.chown() 方法用于更改文件所有者,如果不修改可以设置为 -1, 你需要超级用户权限来执行权限修改操作.高佣联盟 www.cgewang.com 只支持在 Unix 下使用. 语法 c ...

  7. 4.2 省选模拟赛 流浪者 容斥dp

    求出期望 所有情况很好搞 C(n+m-2,n-1). 也就是说求出所有情况的和乘以上面总方案的逆元即可. 可以发现所有情况和经过多少个障碍点有关 和所处位置无关. 简单的设f[i]表示从1,1到n,m ...

  8. Spark初探

    Apache Spark是一个针对大规模数据的快速.统一处理引擎. One stack rule them all 1-Stream Processing :spark Streaming 2-Ad- ...

  9. 70道Spring面试题

    1. 什么是spring? Spring 是个java企业级应用的开源开发框架.Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用.Spring 框架目标是简化Jav ...

  10. 简单的 vector

    #pragma once #include <memory.h> #include <stdlib.h> #include <iostream> using std ...