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 />

最终效果

相关推荐
来杯@Java14 小时前
学生选课管理系统(基于springboot+vue前后端分离的项目)计算机毕业设计java
java·spring boot·spring·vue·毕业设计·maven·mybatis
医疗信息化王工1 天前
医院自律端系统——预警处置模块全栈实战(ASP.NET Core + Vue3 + Quartz 定时调度)
mysql·postgresql·vue·asp.net core·quartz
大大杰哥1 天前
Vue2学习(1)--了解基本方法与概念
javascript·学习·vue
Agatha方艺璇2 天前
前端开发技术复习笔记
vue·bootstrap·css3·html5·web
小葛要努力2 天前
创建vue2项目
程序人生·vue
七仔啊2 天前
基于海康门禁的人员计数系统
vue
步十人3 天前
【Vue3】前置知识简单概述(包括ES6核心语法,模块化ESM以及npm基础)
arcgis·npm·vue·es6
有梦想的程序星空4 天前
【环境配置】Vue3项目离线化本地部署echarts全攻略
前端·javascript·vue·echarts
向日的葵0064 天前
vue路由(二)
前端·javascript·vue.js·vue
小妖6665 天前
Hydration completed but contains mismatches
javascript·vue·vuepress