之前面试的时候,面试官问了一道关于如何设置暗黑模式的问题,当时第一想法就是全局更改样式,但是具体说不出个所以然,最近在业务开发的时候发现vant4也支持暗黑了,故而抽空拜读一下vant4关于暗黑模式的源码,在此记录一下。
默认样式
export function getDefaultTheme() {
const cache = window.localStorage.getItem('vantTheme');
if (cache) {
return cache;
}
const useDark =
window.matchMedia &&
window.matchMedia('(prefers-color-scheme: dark)').matches;
return useDark ? 'dark' : 'light';
}
这里先判断本地是否有缓存的主题样式属性,有的话先用缓存的,没有的话则判断用户的操作系统是否有设置主题色。
window.matchMedia():返回一个新的 MediaQueryList 对象,表示指定的媒体查询字符串解析后的结果。 prefers-color-scheme:是 CSS 媒体特性【@media】用于检测用户是否有将操作系统的主题色设置为亮色【light】或者暗色【dark】,这俩个也是 prefers-color-scheme 的重要属性。
切换事件
toggleTheme() {
this.currentTheme = this.currentTheme === 'light' ? 'dark' : 'light';
}
监听 toggleTheme 属性的变化,对 html 标签的样式进行替换
watch: {
currentTheme: {
handler(newVal, oldVal) {
window.localStorage.setItem('vantTheme', newVal);
document.documentElement.classList.remove(`van-doc-theme-${oldVal}`);
document.documentElement.classList.add(`van-doc-theme-${newVal}`);
// 通知子iframe元素(mobile)修改样式
syncThemeToChild(newVal);
},
immediate: true,
},
}
样式文件定义好正常模式和暗黑模式的 css 样式
.van-doc-theme-light {
// text
--van-doc-text-color-1: var(--van-doc-black);
--van-doc-text-color-2: var(--van-doc-gray-8);
--van-doc-text-color-3: #34495e;
--van-doc-text-color-4: var(--van-doc-gray-6);
--van-doc-link-color: var(--van-doc-blue);
// background
--van-doc-background: #eff2f5;
--van-doc-background-2: var(--van-doc-white);
--van-doc-background-3: var(--van-doc-white);
--van-doc-header-background: #011f3c;
--van-doc-border-color: var(--van-doc-gray-2);
// code
--van-doc-code-color: #58727e;
--van-doc-code-comment-color: var(--van-doc-gray-6);
--van-doc-code-background: var(--van-doc-gray-1);
// blockquote
--van-doc-blockquote-color: #2f85da;
--van-doc-blockquote-background: #ecf9ff;
}
.van-doc-theme-dark {
// text
--van-doc-text-color-1: var(--van-doc-white);
--van-doc-text-color-2: rgba(255, 255, 255, 0.9);
--van-doc-text-color-3: rgba(255, 255, 255, 0.75);
--van-doc-text-color-4: rgba(255, 255, 255, 0.6);
--van-doc-link-color: #1bb5fe;
// background
--van-doc-background: #202124;
--van-doc-background-2: rgba(255, 255, 255, 0.06);
--van-doc-background-3: rgba(255, 255, 255, 0.1);
--van-doc-header-background: rgba(1, 31, 60, 0.3);
--van-doc-border-color: #3a3a3c;
// code
--van-doc-code-color: rgba(200, 200, 200, 0.85);
--van-doc-code-comment-color: var(--van-doc-gray-7);
--van-doc-code-background: rgba(0, 0, 0, 0.24);
// blockquote
--van-doc-blockquote-color: #bae6fd;
--van-doc-blockquote-background: rgba(7, 89, 133, 0.25);
}
总结:应用的暗黑模式说到底就是样式的切换,提前定义好样式文件,然后通过 document.documentElement.classList 对相应标签的样式进行替换。