Nuxt3 实战 (八):优雅的实现暗黑主题模式

前言

Nuxt3 中要实现暗黑模式,需要用到一个库:color-mode,它可以帮助我们很轻易地实现暗黑模式切换。

具体使用

  1. 安装 @nuxtjs/color-mode 依赖:
powershell 复制代码
pnpm add @nuxtjs/color-mode -D
  1. 打开 nuxt.config.ts 配置文件注入依赖:
ts 复制代码
export default defineNuxtConfig({
  modules: ['@nuxtjs/color-mode']
})
  1. 你也可以根据项目实际情况自定义配置,以下是一些默认配置:
ts 复制代码
import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
  modules: ['@nuxtjs/color-mode'],
  colorMode: {
    preference: 'system', // default value of $colorMode.preference
    fallback: 'light', // fallback value if not system preference found
    hid: 'nuxt-color-mode-script',
    globalName: '__NUXT_COLOR_MODE__',
    componentName: 'ColorScheme',
    classPrefix: '',
    classSuffix: '-mode',
    storageKey: 'nuxt-color-mode'
  }
})

具体的使用文档:NuxtColorMode

按钮模式

  1. src/components 中新建 ColorMode/index.vue 文件:
html 复制代码
 <script setup lang="ts">
 const colorMode = useColorMode()

 // 切换模式
 const setColorMode = () => {
   colorMode.value = colorMode.value === 'dark' ? 'light' : 'dark'
 }

 // 判断是否支持 startViewTransition API
 const enableTransitions = () =>
   'startViewTransition' in document &&
   window.matchMedia('(prefers-reduced-motion: no-preference)').matches

 // 切换动画
 async function toggleDark({ clientX: x, clientY: y }: MouseEvent) {
   const isDark = colorMode.value === 'dark'

   if (!enableTransitions()) {
     setColorMode()
     return
   }

   const clipPath = [
     `circle(0px at ${x}px ${y}px)`,
     `circle(${Math.hypot(
       Math.max(x, innerWidth - x),
       Math.max(y, innerHeight - y)
     )}px at ${x}px ${y}px)`
   ]

   await document.startViewTransition(async () => {
     setColorMode()
     await nextTick()
   }).ready

   document.documentElement.animate(
     { clipPath: !isDark ? clipPath.reverse() : clipPath },
     {
       duration: 300,
       easing: 'ease-in',
       pseudoElement: `::view-transition-${!isDark ? 'old' : 'new'}(root)`
     }
   )
 }
 </script>

 <template>
   <el-tooltip
     :content="`切换${$colorMode.value === 'dark' ? '白天' : '黑夜'}模式`"
     placement="bottom"
   >
     <el-button
       circle
       text
       @click="toggleDark"
     >
       <Icon
         :name="$colorMode.value === 'dark' ? 'i-heroicons-moon-solid' : 'i-heroicons-sun-solid'"
         class="h-5 w-5"
       />
     </el-button>
   </el-tooltip>
 </template>

 <style>
 ::view-transition-old(root),
 ::view-transition-new(root) {
   animation: none;
   mix-blend-mode: normal;
 }

 ::view-transition-old(root),
 .dark::view-transition-new(root) {
   z-index: 1;
 }

 ::view-transition-new(root),
 .dark::view-transition-old(root) {
   z-index: 9999;
 }
 </style>
  1. 在需要的地方加载组件:
html 复制代码
<ColorMode />

最终效果

相关推荐
Java陈序员7 小时前
自建 Claude Code 镜像!一站式开源中转服务!
docker·node.js·vue·claude·claude code
呆头鸭L8 小时前
Electron进程通信
前端·javascript·electron·前端框架·vue
木斯佳11 小时前
前端八股文面经大全: 蓝色光标前端一面OC(2026-03-23)·面经深度解析
前端·面试·vue·校招·js·面经
蜡台1 天前
SPA(Single Page Application) Web 应用(即单页应用)架构模式 更新
前端·架构·vue·react·spa·spa更新
Betelgeuse761 天前
Django 项目远程服务器部署教程:从开发到生产
python·django·vue
初级见习猿工2 天前
使用pdfjs-dist在Vue 3中实现PDF文件浏览器预览
javascript·vue·pdfjs-dist
A_nanda2 天前
ZR.Admin.NET后台管理系统
vue·.net·zradmin
十七号程序猿2 天前
Java图书管理系统 | 无需配置任何环境,双击一键启动,开箱即用
java·spring boot·vue·毕业设计·毕设·源代码管理
终端鹿3 天前
Vue3 + Pinia 实战深度解析
vue
BugShare3 天前
有趣味的登录页它踏着七彩祥云来了
vue·css3