Vue3+Setup+TypeScript实现主题切换(浅色、深色、跟随系统)

使用 Vue 3 的 Composition API、 TypeScript 以及 <script setup> 语法糖,实现动态主题切换,能够在 ‘light’(明亮)、‘dark’(暗黑)和 ‘system’(系统)主题之间切换,并且使用 localStorage 做了状态缓存。代码十分精简,提供 JavaScript 和 TypeScript 版本,也可以在线体验此功能:play.vuejs.org

基本实现

script

  • const theme = ref<ThemeType>((localStorage.getItem('theme') as ThemeType) || 'light') 使用 Vue 的 ref 函数创建一个响应式引用,保存当前选择的主题。尝试从 localStorage 获取保存的主题,如果没有则默认为 'light'
  • watch 来观察 theme 的变化,当 theme 变化时修改 html 的 class,当 theme 设置为 ‘system’ 时,会根据当前系统的主题来设置对应的 class。
  • setTheme 函数用来将用户选择的主题保存到 localStorage 并更新 theme
  • handleChange 函数为 <select> 元素的 change 事件提供处理逻辑,它会调用 setTheme 以更新并保存用户选择的新主题。

template

显示当前主题,并有一个下拉菜单让用户选择主题。

style

定义了两个 css 变量,用于设置背景颜色和文字颜色。.dark 类通过覆盖 CSS 变量,实现暗黑模式的配色方案。

完整代码

TypeScript

<script setup lang="ts">
import { ref, watch } from 'vue'

type ThemeType = 'light' | 'dark' | 'system'

const theme = ref<ThemeType>((localStorage.getItem('theme') as ThemeType) || 'light')

watch(
  theme,
  (val) => {
    const root = window.document.documentElement

    root.classList.remove('light', 'dark')

    if (theme.value === 'system') {
      const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
        ? 'dark'
        : 'light'

      root.classList.add(systemTheme)
      return
    }

    root.classList.add(val)
  },
  {
    immediate: true,
  }
)

const setTheme = (value: ThemeType) => {
  localStorage.setItem('theme', value)
  theme.value = value
}

const handleChange = (
  event: Event & {
    target: HTMLSelectElement
  }
) => {
  const value = event.target.value as ThemeType
  setTheme(value)
}
</script>

<template>
  <div>
    {{ theme }}
    <select v-model="theme" @change="handleChange">
      <option value="light">Light</option>
      <option value="dark">Dark</option>
      <option value="system">System</option>
    </select>
  </div>
</template>

<style>
:root {
  --background: #ffffff;
  --text: #09090b;
}

.dark {
  --background: #09090b;
  --text: #f9f9f9;
}

html,
body,
#app {
  height: 100%;
}

body {
  background-color: var(--background);
  color: var(--text);
}
</style>

JavaScript

<script setup>
import { ref, watch } from 'vue'

const theme = ref((localStorage.getItem('theme')) || 'light')

watch(
  theme,
  (val) => {
    const root = window.document.documentElement

    root.classList.remove('light', 'dark')

    if (theme.value === 'system') {
      const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
        ? 'dark'
        : 'light'

      root.classList.add(systemTheme)
      return
    }

    root.classList.add(val)
  },
  {
    immediate: true,
  }
)

const setTheme = (value) => {
  localStorage.setItem('theme', value)
  theme.value = value
}

const handleChange = (event) => {
  const value = event.target.value
  setTheme(value)
}
</script>

<template>
  <div>
    {{ theme }}
    <select v-model="theme" @change="handleChange">
      <option value="light">Light</option>
      <option value="dark">Dark</option>
      <option value="system">System</option>
    </select>
  </div>
</template>

<style>
:root {
  --background: #ffffff;
  --text: #09090b;
}

.dark {
  --background: #09090b;
  --text: #f9f9f9;
}

html,
body,
#app {
  height: 100%;
}

body {
  background-color: var(--background);
  color: var(--text);
}
</style>
### 关于 UniApp UI 框架的使用指南、示例和教程 #### 一、UniApp 基础组件概述 UniApp 提供了一系列的基础视图容器组件,这些组件构成了应用界面的核心部分。开发者可以通过学习这些基础组件来构建简单的页面布局[^1]。 #### 二、高级组件与 UI 组件库推荐 对于更复杂的功能需求,可以考虑使用 TMUI 这样的高性能跨平台 UI 组件库。TMUI 支持 Vue3TypeScript,并且能够适配多个平台(如 Uni App、微信小程序、H5)。它不仅提供了丰富的组件集合,还允许用户根据实际需求调整样式属性,比如颜色渐变、暗黑模式等[^2]。 如果需要更多的选择,则可以从 DCloud 官方插件市场找到适合项目的 UI 解决方案。以下是几个常见的选项及其特点: - **uView UI**: 功能齐全,文档详尽易懂; - **colorUI CSS 库**: 注重设计美感,适用于追求视觉效果的应用场景; - **unify UI**: 主要面向 nvue 技术栈用户提供支持; - **mypUI**: 同样强调对 nvue 的兼容性; - **nPro 商业库**: 结合云端一体化特性,特别针对 vue3 用户进行了优化并增加了类型脚本的支持; - **first UI & 图鸟 UI**: 分别推出免费开源版本以及付费增强功能的产品线; - **s-ui**: 另一款注重外观表现力的选择[^3]. 此外还有像 PIUI 这种专注于打造高质量体验的开源项目可供参考[^5], 或者利用 Vant Weapp 版本来实现特定的小程序定制化需求[^4]。 #### 三、性能调优技巧分享 无论选用哪种类型的工具包,在实际编码过程中都应关注如何提升渲染效率等问题。例如减少不必要的 DOM 操作次数,合理设置懒加载策略等等都是值得深入研究的方向之一. ```javascript // 示例代码展示如何动态切换主题风格 (假设采用 TMUI 实现) import { ref } from &#39;vue&#39;; export default { setup() { const currentTheme = ref(&#39;light&#39;); // 默认浅色系 function toggleTheme(){ if(currentTheme.value ===&#39;dark&#39;){ currentTheme.value=&#39;light&#39; } else{ currentTheme.value=&#39;dark&#39; } } return {currentTheme,toggleTheme}; }, } ``` 以上片段演示了一个简单的方法用来改变全局主题设定(深色/明亮),这通常会涉及到修改根节点上的 class 属性或者直接操作 style 对象中的键值对。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值