【主题切换详细说明】介绍一种主题切换的方案,尽可能的教会大家使用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 加上。

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

相关推荐
冰暮流星8 分钟前
javascript的switch语句介绍
java·前端·javascript
做科研的周师兄35 分钟前
【MATLAB 实战】|多波段栅格数据提取部分波段均值——批量处理(NoData 修正 + 地理信息保真)_后附完整代码
前端·算法·机器学习·matlab·均值算法·分类·数据挖掘
da_vinci_x41 分钟前
图标量产:从“手绘地狱”到“风格克隆”?Style Reference 的工业化实战
前端·游戏·ui·prompt·aigc·设计师·游戏美术
利刃大大1 小时前
【ES6】变量与常量 && 模板字符串 && 对象 && 解构赋值 && 箭头函数 && 数组 && 扩展运算符 && Promise/Await/Async
开发语言·前端·javascript·es6
天若有情6731 小时前
ES6 模块与 CommonJS 的区别详解
前端·javascript·es6
大猫会长1 小时前
postgreSQL中,RLS的using与with check
开发语言·前端·javascript
慧一居士1 小时前
vite.config.ts 配置使用说明,完整配置示例
前端
wusp19941 小时前
nuxt3模块化API架构
前端·javascript·nuxt3
沛沛老爹1 小时前
Web开发者进阶AI:企业级Agent Skills安全策略与合规架构实战
前端·人工智能·架构
遗憾随她而去.2 小时前
前端首屏加载时间的度量:FCP、LCP等指标的规范理解
前端