lucas-themes
v1.0.3
Published
A framework-agnostic themes manager supporting React and Vue
Downloads
12
Readme
lucas-themes
一个框架无关的主题管理 npm 包,支持 React、Vue 3 和 Vue 2,采用核心层+适配层架构。
特性
- 🎨 完全自定义主题类名
- ⚡ 框架无关的核心层
- 🔄 支持系统主题自动检测
- 💾 自动持久化到 localStorage
- 🚀 SSR 防闪烁支持
- 🏎️ 高性能异步更新:内置 DOM 更新队列,同一帧内多次切换自动去重合并
- 💎 React 无抖动水合:优化 React 挂载逻辑,彻底消除服务端渲染的水合布局抖动
- 📦 支持 class、data-theme 或同时使用两种方式
- 🔌 TypeScript 完整支持
- 🎯 支持 React、Vue 3、Vue 2
- 📚 完整的文档和示例
为什么选择 lucas-themes?
| 特性 | next-themes | lucas-themes | | :------------- | :--------------- | :------------------------------ | | 支持框架 | 仅 React | React, Vue 3, Vue 2 | | 应用粒度 | 全局 (html/body) | 局部隔离 (Custom Container) | | 更新策略 | 同步执行 | 高性能异步去重队列 | | 水合体验 | 较好 | 极佳 (无额外 DOM 节点) | | 多实例支持 | 不支持 | 完全支持,互不干扰 |
安装
npm install lucas-themes
# 或
yarn add lucas-themes
# 或
pnpm add lucas-themes环境要求
lucas-themes 使用 peerDependencies,需要根据使用的框架安装对应版本:
- React:
>= 18.0.0(使用了useSyncExternalStoreAPI) - Vue 3:
>= 3.0.0 - Vue 2:
>= 2.2.0(使用了provide/injectAPI)
这些依赖是可选的,你只需要安装你使用的框架版本即可。
React 使用
基础用法
import { ThemeProvider, useTheme } from 'lucas-themes/react'
function App() {
return (
// themes 可选,默认值为 ['light', 'dark', 'system']
<ThemeProvider>
<ThemedComponent />
</ThemeProvider>
)
}
function ThemedComponent() {
const { theme, setTheme, resolvedTheme } = useTheme()
return (
<div>
<p>当前主题: {theme}</p>
<p>解析后主题: {resolvedTheme}</p>
<button onClick={() => setTheme('light')}>切换到浅色</button>
<button onClick={() => setTheme('dark')}>切换到深色</button>
<button onClick={() => setTheme('system')}>跟随系统</button>
</div>
)
}自定义主题列表
如果需要自定义主题,可以传入 themes 属性:
<ThemeProvider themes={['light', 'dark', 'theme-blue', 'theme-purple']} defaultTheme='dark' enableSystem={true}>
<ThemedComponent />
</ThemeProvider>使用 data-theme 属性
<ThemeProvider themes={['light', 'dark']} attribute='data-theme'>
<App />
</ThemeProvider>同时使用 class 和 data-theme
<ThemeProvider themes={['light', 'dark']} attribute='both'>
<App />
</ThemeProvider>自定义存储键
<ThemeProvider themes={['light', 'dark']} storageKey='my-app-theme'>
<App />
</ThemeProvider>主题变化回调
<ThemeProvider
themes={['light', 'dark']}
onChange={theme => {
console.log('主题已切换为:', theme)
}}
>
<App />
</ThemeProvider>Vue 3 使用
基础用法
<template>
<!-- themes 可选,默认值为 ['light', 'dark', 'system'] -->
<ThemeProvider>
<ThemedComponent />
</ThemeProvider>
</template>
<script setup>
import { ThemeProvider, useTheme } from 'lucas-themes/vue'
const { theme, setTheme, resolvedTheme } = useTheme()
</script>自定义主题列表
如果需要自定义主题,可以传入 themes 属性:
<ThemeProvider :themes="['light', 'dark', 'theme-blue']" default-theme="dark" :enable-system="true">
<ThemedComponent />
</ThemeProvider>使用 data-theme 属性
<ThemeProvider :themes="['light', 'dark']" attribute="data-theme">
<App />
</ThemeProvider>同时使用 class 和 data-theme
<ThemeProvider :themes="['light', 'dark']" attribute="both">
<App />
</ThemeProvider>自定义存储键
<ThemeProvider :themes="['light', 'dark']" storage-key="my-app-theme">
<App />
</ThemeProvider>主题变化回调
<ThemeProvider :themes="['light', 'dark']" @change="theme => console.log('主题已切换为:', theme)">
<App />
</ThemeProvider>Vue 2 使用
基础用法
<template>
<ThemeProvider :themes="['light', 'dark', 'theme-blue']" default-theme="dark" :enable-system="true">
<ThemedComponent />
</ThemeProvider>
</template>
<script>
import { ThemeProvider, useTheme } from 'lucas-themes/vue2'
export default {
components: { ThemeProvider },
mixins: [useTheme()],
}
</script>使用 data-theme 属性
<ThemeProvider :themes="['light', 'dark']" attribute="data-theme">
<App />
</ThemeProvider>同时使用 class 和 data-theme
<ThemeProvider :themes="['light', 'dark']" attribute="both">
<App />
</ThemeProvider>API
ThemeProvider Props
| 属性 | 类型 | 默认值 | 说明 |
| ------------ | ----------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| themes | string[] | 必填 | 主题列表 |
| defaultTheme | string | themes[0] | 默认主题 |
| enableSystem | boolean | false | 是否启用系统主题 |
| storageKey | string | 'theme' | localStorage 存储键 |
| attribute | 'class' \| 'data-theme' \| 'both' | 'class' | 应用主题的方式 |
| container | HTMLElement \| null | document.documentElement | 容器元素(可选)- undefined: 未指定,使用默认- null: 期望有容器但暂时为 null- HTMLElement: 有容器 |
| containerRef | RefObject<HTMLElement> | - | 容器元素的 ref(React,可选) |
| onChange | (theme: string) => void | - | 主题变化回调 |
useTheme 返回值
| 属性 | 类型 | 说明 |
| ------------- | -------------------------------- | --------------------------- |
| theme | string \| undefined | 当前设置的主题 |
| resolvedTheme | string \| undefined | 解析后的主题(处理 system) |
| setTheme | (theme: string) => void | 设置主题 |
| themes | string[] | 所有可用主题 |
| systemTheme | 'light' \| 'dark' \| undefined | 系统主题 |
核心 API
如果需要直接使用核心层(不依赖框架):
import { ThemeManager } from 'lucas-themes'
const manager = new ThemeManager({
themes: ['light', 'dark'],
defaultTheme: 'light',
enableSystem: true,
})
manager.init()
manager.setTheme('dark')
const currentTheme = manager.getTheme()
const resolvedTheme = manager.getResolvedTheme()
// 订阅主题变化
const unsubscribe = manager.subscribe(theme => {
console.log('主题变化:', theme)
})
// 清理
manager.destroy()CSS 示例
使用 class 方式
.light {
background-color: #ffffff;
color: #000000;
}
.dark {
background-color: #000000;
color: #ffffff;
}
.theme-blue {
background-color: #1e40af;
color: #ffffff;
}使用 data-theme 方式
[data-theme='light'] {
background-color: #ffffff;
color: #000000;
}
[data-theme='dark'] {
background-color: #000000;
color: #ffffff;
}
[data-theme='theme-blue'] {
background-color: #1e40af;
color: #ffffff;
}同时使用两种方式
.light,
[data-theme='light'] {
background-color: #ffffff;
color: #000000;
}
.dark,
[data-theme='dark'] {
background-color: #000000;
color: #ffffff;
}SSR 支持
包内置了 SSR 防闪烁脚本,会在页面加载前应用主题,避免闪烁。
对于 Next.js,可以在 _document.tsx 中手动注入脚本:
import { getThemeScript } from 'lucas-themes'
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html>
<Head>
<script
dangerouslySetInnerHTML={{
__html: getThemeScript({
themes: ['light', 'dark'],
defaultTheme: 'light',
enableSystem: true,
}),
}}
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}文档
完整的文档请查看 docs 目录:
示例项目
查看 examples 目录获取完整示例:
许可证
MIT
