【主题切换详细说明】介绍一种主题切换的方案,尽可能的教会大家使用css变量实现主题切换

大家下午好。今天我们来介绍一种比较简单易实现的主题切换方案,接下来我将尽可能的把这种方案讲的清清楚楚明明白白。写的不好的地方也请大家伙见谅。

正文之前

近来,在项目上突遇主题切换的需求,一般来说是系统预设几套主题,如 浅|亮色(light)、暗色(dark)等等,其中还涉及到不同主题图片等的静态资源变更,以及echarts等的图表颜色变更。接下来本文将介绍较为简单的实现方案。

一: 主题切换方案

目前较为主流的主题切换方案主要有两种:

1. 方案一: css 变量切换主题(推荐)

  • 优点:
    • 简单,兼容性好,适合大部分项目,兼容绝大多数现代主流浏览器;
    • 新增或修改主题方便灵活,仅需新增或修改CSS变量即可,在var()绑定样式变量的地方就会自动更换;
    • 在需要切换主题的地方利用var()绑定变量即可,不存在优先级问题;
    • 不用重新加载样式文件,在样式切换时不会有卡顿
  • 缺点:
    • 不兼容ie(但可忽略不计);
    • 首屏加载时会牺牲一些时间加载样式资源

2. 方案二: 使用sass/scss、less等预处理器切换主题(推荐,本文暂不介绍)

  • 优点:
    • 不用重新加载样式文件,在样式切换时不会有卡顿;
    • 在需要切换主题的地方利用mixin混合绑定变量即可,不存在优先级问题;
    • 新增或修改主题方便灵活,仅需新增或修改SCSS变量即可,经过编译后会将所有主题全部编译出来
  • 缺点: 首屏加载时会牺牲一些时间加载样式资源

3. 方案三: 使用传统方案切换主题,如 动态加载link,类名切换等(不推荐,本文不会介绍)

  • 优点:
    • 兼容性最佳;
    • 实现了按需加载,提高了首屏加载时的性能
  • 缺点:
    • 代码量多,需提前写好几套样式代码,比较繁琐;
    • 主题样式表内定义不当,会有优先级问题;
    • 动态加载样式文件,如果文件过大网络情况不佳的情况下可能会有加载延迟,导致样式切换不流畅;
    • 各个主题样式是写死的,后续针对某一主题样式表修改或者新增主题也很麻烦

实现效果

css变量实现

CSS变量实现过程

实现思路

  • 定义预设主题并导入
  • 定义全局主题变量 theme
  • html 根元素加入 data-theme 自定义属性
  • 使用 var(--bg-color) 取相对应的色值,如果需要 js 动态取值变更,则使用 getPropertyValue API 取值赋值即可
  • 动态绑定也可直接使用 var(--bg-color) 即可
  • 静态资源通过 require 动态加载
1. 创建theme.css,定义预设变量

这里咱只定义了两套主题,浅色与暗系,大家有多套主题也是一样的。然后在 main.js 导入主题。

2. 创建 store,定义全局变量 theme

定义全局变量且保存在本地缓存中(localStorage/cookie/sessionStorage 都可以),全局变量可以使用 vuex, pinia 等,由于本文实现是使用 vue2.6.11,所以在本文中采用 vuex 去定义操作。

3. 在 html 跟元素添加自定义属性
  • HelloWorld 组件中定义一个切换主题按钮,点击切换组件时触发 vuex 变更主题的 mutations,随即更改主题并且给根元素定义 data-theme 属性并赋值

  • 根据 data-theme 属性的值辨别当前主题,结合咱第一步创建的预设主题变量,再使用 var() 取主题变量就能完成初步主题切换的需求了

  • app.vue 为例,使用 var() 实现切换

效果

可以看到,咱背景颜色,字体颜色已然完美实现了主题切换的需求。

4. 静态资源变更, js 取值赋值等

在上面已经完成了组件在 css 中切换主题色,但是切换的时候有时候需要把静态资源也同步更新,以图片为例:切换主题时,把 vue 的 logo 切换为 react 的 logo。

  • assets 文件夹下根据主题值新建文件夹,然后就可以根据 theme 值的变化使用 require 去变更静态资源

  • 动态绑定

js 取主题值变更,一般应用在 echarts 图表类或者其他不能直接使用 var() 取切换的场景。

  • 创建 echarts 柱状图

  • 为了方便取值,本人在 utils 中定义了 getPropertyValue 方法, getPropertyValue API 作用是返回元素的css值,在前面使用 getComputedStyle 为了拿到计算后最终的 css 属性,与之对应的还有 setProperty('background', 'red') 属性,作用是给元素设置新的 css 属性值。

  • 效果如下

  • 这样就可以使用 getPropertyValue 配合 echarts 实现切换主题了,还记得前面定义预设主题吗,我们定义了 --charts-bar-bg --charts-bar-color 两个变量。监听 theme 的变化,从而改变 echarts 的色值

完美
问题

按照以上步骤能实现主题切换,但是此时一刷新就会发现,页面会回归到默认的浅色主题,因为在页面刚加载时是没有 data-theme 属性的,因此我们得在页面加载的时候把 data-theme 加上。

完成,感谢大家阅读。如有讲的不清楚的地方,可留言批评。

相关推荐
雨中奔跑的小孩几秒前
electron打包部署vue项目
javascript·vue.js·electron
ZZZCY200312 分钟前
路由策略与路由控制实验
前端·网络
shawya_void21 分钟前
javaweb-day01-html和css初识
前端·css·html
khatung22 分钟前
React——useReducer
前端·javascript·vscode·react.js·前端框架·1024程序员节
思考的橙子24 分钟前
CSS之3D转换
前端·css·3d
木子七1 小时前
vue3-setup中使用响应式
前端·vue
廖子默1 小时前
提供html2canvas+jsPDF将HTML页面以A4纸方式导出为PDF后,内容分页时存在截断的解决思路
前端·pdf·html
Moment1 小时前
毕业半年,终于拥有了两个近 500 star 的开源项目了 🤭🤭🤭
前端·后端·开源
光影少年2 小时前
react和vue图片懒加载及实现原理
前端·vue.js·react.js
AndyGoWei2 小时前
react react-router-dom history 实现原理,看这篇就够了
前端·javascript·react.js