环境信息:
日期:2022-08-05
node版本:v14.15.4
"sass": "1.26.8",
"sass-loader": "8.0.2",
本次实现的是基于花裤衩大佬的 vue-element-admin 或者 vue-admin-template 的前端框架实现的主题换肤功能。
具体功能为预设几种配色方案,点击切换主题后:elementUI主题色、侧边栏及svg图标、具体路由页面中指定元素也会随之改变。
将分为以下三步来逐步实现完整的主题换肤功能。各位可根据自己的需求分步观看。
- 基础的elementUI主题变色 (最基础的换肤功能,仅变更elementUI相关组件颜色)
- 左侧栏随之变色 (若侧边栏选中item时背景色、选中文字色、svg图表需要跟随主题变色,请看该步骤)
- 页面中自定义元素随之变色 (若页面中某些元素需要跟随主题变色,请看该步骤)
1. 实现elementUI换色
1.1 生成elementUI配色文件
首先安装elementUI主题工具。
cnpm install element-themex -g (注:此处注意最好使用cnpm,使用npm可能报错)
npm i element-theme-chalk -D
安装完毕后,执行
et -i
此时,在本项目根目录将会生成element-variables.scss文件。进入该文件,对需要修改的配色进行更改,保存 。此处我将主题色修改为 #eb507e 。
随后执行
et
执行完毕后,根目录将多出一个theme文件夹。
我们需要的是该文件夹中的fonts文件夹以及index.css文件。
此时,index.css中就是使用我们修改的配色写成的elementUI样式文件。由于我们可能会有多套不同主题进行切换,为了区分不同的样式文件,我们需要给index.css文件中每个样式前加上当前颜色的标注(命名空间)。这件事使用gulp的css-wrap功能来实现。
在做下一件事情之前,我们需要在src目录下新建theme文件夹,用于存放最后生成的主题文件。
1.2 使用gulp的css-wrap为所有选择器加上命名空间
首先,安装gulp。
//1.安装gulp:
npm install gulp
//2.安装gulp-clean-css
npm install gulp-clean-css
//3.安装gulp-css-wrap
npm install gulp-css-wrap
随后,在项目根目录下新建名为gulpfile.js的文件。
需要注意该文件内涉及颜色的地方要和之前自己修改的主题色一致。
// gulpfile.js
var path = require('path')
var gulp = require('gulp')
var cleanCSS = require('gulp-clean-css')
var cssWrap = require('gulp-css-wrap')
gulp.task('css-wrap', function () {
return gulp.src(path.resolve('./theme/index.css'))
/* 找需要添加命名空间的css文件,支持正则表达式 */
.pipe(cssWrap({
selector: '.custom-eb507e' /* 添加的命名空间 */
}))
.pipe(cleanCSS())
.pipe(gulp.dest('src/theme/#eb507e')) /* 存放的目录 */
})
保存后,在终端执行以下命令以使用css-wrap:
gulp css-wrap
执行完毕后,观察src/theme文件夹,已经按照指定规则生成目录,并包含了处理后的文件。
查看处理后的文件可以看到所有选择器被加上了我们自己指定的命名空间。
最后,将根目录下的theme文件夹中的fonts目录拷贝至src/theme。至此,一个主题所需的文件就准备完成了。
1.3 准备工作完成后创建新主题的流程
由于我们是多套主题切换,在此演示前面准备工作完毕后想要添加一个新的主题如何操作。
1. 之前我们生成过根目录下的element-variables.scss文件,故我们只需先去该文件中再次更改配色。本次使用 #2bae85。
保存后,在终端执行et命令,于根目录生成theme文件夹。
2. 前往gulpfile.js,替换颜色变量。
// gulpfile.js var path = require('path') var gulp = require('gulp') var cleanCSS = require('gulp-clean-css') var cssWrap = require('gulp-css-wrap') gulp.task('css-wrap', function () { return gulp.src(path.resolve('./theme/index.css')) /* 找需要添加命名空间的css文件,支持正则表达式 */ .pipe(cssWrap({ selector: '.custom-2bae85' /* 添加的命名空间 */ })) .pipe(cleanCSS()) .pipe(gulp.dest('src/theme/#2bae85')) /* 存放的目录 */ })
保存后,执行gulp css-wrap命令。执行完毕后,新目录创建完成。但是还缺少fonts文件夹。
![]()
3. 将根目录下的theme/fonts文件夹复制到src/theme/#2bae85下。即完成新主题的创建。此时src/theme目录结构如下。
![]()
1.4 引入主题,实现切换
此时我们已经准备好了两个主题,下一步去实现切换功能。
首先于main.js引入主题文件。
// main.js
import '@/theme/#eb507e/index.css'
import '@/theme/#2bae85/index.css'
随后来到Navbar.vue文件,添加切换主题按钮。(个人习惯将该功能放在navbar上,也可以放在其他地方)
<el-dropdown class="avatar-container" trigger="hover">
<el-button type="primary">切换主题</el-button>
<el-dropdown-menu slot="dropdown" class="user-dropdown">
<el-dropdown-item @click.native="toggleTheme('2bae85')">
<span style="display: block">亚丁绿</span>
</el-dropdown-item>
<el-dropdown-item @click.native="toggleTheme('eb507e')">
<span style="display: block">初荷红</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
其中点击后调用的方法定义如下。
toggleTheme(color) {
this.theme = color
// bus.$emit('changeTheme', color)
this.toggleClass(document.body, `custom-${color}`)
localStorage.setItem('theme', color)
},
toggleClass(element, className) {
if (!element || !className) {
return
}
element.className = className
},
观察代码,其实就是在body上添加了className。例如点击“亚丁绿”,此时html结构就会变为如图所示的样子。
这个 custom-2bae85 类,就对应了之前我们使用gulp css-wrap处理过后的文件中的命名空间。效果图如下。
未完待续...