暗黑模式

217 阅读2分钟

之前面试的时候,面试官问了一道关于如何设置暗黑模式的问题,当时第一想法就是全局更改样式,但是具体说不出个所以然,最近在业务开发的时候发现vant4也支持暗黑了,故而抽空拜读一下vant4关于暗黑模式的源码,在此记录一下。

image.png

默认样式

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,
    },
}

image.png

样式文件定义好正常模式和暗黑模式的 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 对相应标签的样式进行替换。