实战:让你的网站支持一键切换深色模式的核心要点

1,515 阅读2分钟

这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战

深色模式对于经常大部分人并不陌生,大多数的 APP 和 web 网页都已经支持了深色模式。深色模式通过调整整体颜色和对比度,从而降低白点值和屏幕亮度,保护用户视力,是一个网站用户体验的评判标准。 如何手动的实现网站的深色/浅色模式,而不使用第三方的插件支持,掌握几个核心要点即可。

  • 准备深色/浅色 CSS 样式
  • 监听系统模式切换
  • 本地化存储当前模式
  • 手动切换主题的实现

样式准备

这里采用的是两份样式文件,分别为ThemeLight.lessThemeDark.less,并完全引入。具体为控制 body 标签的样式类名,实现切换至对应的样式文件。

document.querySelector("html").setAttribute("class", `${theme}-mode`);

核心实现

新建theme.js作为模式控制相关的核心,设定两个基础方法,setget,用于设置和获取当前的主题模式。 set方法主要是切换 body 标签的样式,从而实现整体的视觉切换,同时将切换后的主题存到浏览器缓存,进而在用户刷新或者下一次进入的时候,可以保持上一次切换的主题模式。 get会优先从本地存储获取之前设置的模式,如果不存在则调用set方法设置默认主题。 具体实现如下:

export const useTheme = () => {
  const themeMode = {};

  /**
   * 设置主题模式
   * @param {String} theme 主题
   * @return {String} 主题
   */
  themeMode.set = (theme = "light") => {
    document.querySelector("html").setAttribute("class", `${theme}-mode`);
    window.localStorage.setItem("theme", theme);
    return theme;
  }

  /**
   * 获取当前的主题模式,初始化为 light
   * @return {String} 主题
   */
  themeMode.get = () => {
    const currentTheme = window.localStorage.getItem("theme");

    return currentTheme ? currentTheme : themeMode.set("light");
  }

  return {
    themeMode
  }
}

手动触发

这一块是放在主题切换按钮组件中的,节选了一部分,引入useTheme后即可调用set方法去手动设置主题。

const { themeMode } = useTheme();

// 手动触发主题切换
const setCurrentThemeMode = () => {
	const val = props.themeMode === "light" ? "dark" : "light";
	const setThemeMode = themeMode.set(val);

	emit("change", setThemeMode);
};

系统监听

这里用到的是 window 的matchMediaAPI,具体实现如下:

const { themeMode } = useTheme();

// 监听系统主题变化
let listeners = {
	dark: (mediaQueryList) => {
		if (mediaQueryList.matches) {
			const setThemeMode = themeMode.set("dark");
			emit("change", setThemeMode);
		}
	},
	light: (mediaQueryList) => {
		if (mediaQueryList.matches) {
			const setThemeMode = themeMode.set("light");
			emit("change", setThemeMode);
		}
	},
};

window
	.matchMedia("(prefers-color-scheme: dark)")
	.addListener(listeners.dark);
window
	.matchMedia("(prefers-color-scheme: light)")
	.addListener(listeners.light);

欢迎阅读其它文章