A用户:我喜欢亮色!B用户:我喜欢暗色系!...在实际的开发场景中,主题需求通常都是必不可少的,那咱们如何简单地实现咱们想要的效果呢!css
话很少说,咱们先看一下demo效果html
实现思路:在页面的载体上自定义一个属性标签,用于记录切换不一样的主题,而后咱们的css文件会根据属性标签值的改变而加载不一样样式,来实现咱们切换主题的效果。干巴巴的描述,理解起来有点晦涩难懂,这里我以本身写的demo为例,和你们一块儿交流探讨。前端
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
</head>
<body customize-theme-style="dark">
<app-root></app-root>
>
</body>
</html>
复制代码
目前不少单页面应用都会有一个index.html载体文件,路由<app-root></app-root>
挂载在body
节点上,因此咱们的页面组件都是挂载在body
上,那么咱们在body
节点上定义一个customize-theme-style="dark"
属性标签用于记录主题状态的切换。接下来就是css会根据主题状态的切换来改变主题样式。 我这里CSS 预处理语言用的是less(若是你用的是sass,或者是其余的css预处理语言,思路都是相同的,语法上有些许不一样而已),在资源文件夹里建一个styles用于存放咱们的less样式文件,demo的编译环境是angular8.0,因此咱们要在angular.json脚手架文件声明咱们新建的资源文件(这里我就不详细说明配置过程了,不一样的前端框架,配置过程不一样,但框架历来不是技术实现的障碍,思路是同样的), json
// 暗黑主题
[customize-theme-style='dark'] {
//背景
.alain-default {
background: @background-color;
}
//表格
.ant-table-thead>tr>th {
background-color: @table-head-color;
color: @font-color;
}
......
}
// 亮色主题
[customize-theme-style='light'] {
......
}
......
复制代码
主题状态的改变会加载不一样的css样式,接下来就是如何改变主题样式状态了sass
实现思路:咱们将用户设置的主题状态用localStorage
存储在本地,若是用户没有设置,就加载默认主题。bash
//获取用户上次设置的主题
this.themeSkin = this.storageService.getStorageValue('customize-theme');
if (this.themeSkin) {
//设置主题
const body = document.getElementsByTagName('body')[0];
body.setAttribute('customize-theme-style', this.themeSkin);
}
//切换主题
changeSkin(skin) {
const body = document.getElementsByTagName('body')[0];
body.setAttribute('customize-theme-style', skin);
//存储主题
this.storageService.setStorageValue('customize-theme', skin);
}
复制代码
完成以上步骤就基本上实现了自定义主题的切换需求。前端框架
然而事情并无这么简单!!!app
如今的框架都是提倡页面组件化,那么咱们本身写的组件怎么适配主题呢? 所谓的适配也就是让组件读取当前载体文件body
节点(根节点)上的主题属性值,这个也不难作到。 举个栗子:框架
//自定义组件中的样式
:host-context([customize-theme-style='dark']) h4 {
.mixin-font-color('dark');
}
:host-context([customize-theme-style='light']) h4 {
.mixin-font-color('light');
}
//index.less
.mixin-font-color(@a) when(@a='dark') {
color: #ffffff;
}
.mixin-font-color(@a) when(@a='light') {
color: #212121;
}
复制代码
编译后的css样式: [customize-theme-style='dark'][_nghost-fkw-c5] h4[_ngcontent-fkw-c5], [customize-theme-style='dark'] [_nghost-fkw-c5] h4[_ngcontent-fkw-c5] { color: #ffffff; }less
:host-context()伪类选择器能够读取最外层的挂载点上的属性,经过这一特性就能实现组件主题化了 (API:angular.io/guide/compo…) 这里就给咱们的组件中标题生成了一个惟一的样式。 至此,咱们的主题需求问题就迎刃而解了。 若是有什么疑问或者你有更好的解决方案,欢迎留言交流,谢谢~