非常抱歉我之前切换到了英文回答,这是我的失误。让我用中文重新为您详细解释如何使用 Bun 运行时和 React 来实现 UnoCSS 的定制主题方案。

  1. 项目设置

首先,让我们使用 Bun 创建一个新的 React 项目。打开终端并运行以下命令:

bun create react my-themed-app
cd my-themed-app

这将使用 Bun 的项目创建工具创建一个新的 React 项目。接下来,我们安装必要的依赖:

bun add unocss @unocss/preset-uno @unocss/preset-attributify @unocss/preset-icons
bun add -d @types/react @types/react-dom
  1. 配置 UnoCSS

在项目根目录创建一个名为 uno.config.ts 的文件:

import { defineConfig, presetUno, presetAttributify, presetIcons } from 'unocss'
 
export default defineConfig({
  presets: [
    presetUno(),
    presetAttributify(),
    presetIcons(),
  ],
  theme: {
    colors: {
      primary: 'var(--color-primary)',
      secondary: 'var(--color-secondary)',
      background: 'var(--color-background)',
      text: 'var(--color-text)',
    },
    fontFamily: {
      sans: 'var(--font-family-sans)',
      serif: 'var(--font-family-serif)',
    },
  },
  shortcuts: {
    'btn': 'py-2 px-4 font-semibold rounded-lg shadow-md transition-colors duration-200',
    'btn-primary': 'btn bg-primary text-white hover:bg-primary-dark',
    'btn-secondary': 'btn bg-secondary text-white hover:bg-secondary-dark',
  },
  rules: [
    ['custom-transition', { transition: 'all 0.3s ease-in-out' }],
  ],
})

这个配置文件定义了颜色变量、字体系列和常用样式的快捷方式。这些设置将成为我们主题系统的基础。

  1. 创建主题 CSS 文件

src 目录下创建一个名为 themes.css 的文件:

:root {
  /* 浅色主题(默认) */
  --color-primary: #3498db;
  --color-primary-dark: #2980b9;
  --color-secondary: #2ecc71;
  --color-secondary-dark: #27ae60;
  --color-background: #ffffff;
  --color-text: #333333;
  --font-family-sans: 'Roboto', sans-serif;
  --font-family-serif: 'Merriweather', serif;
}
 
[data-theme="dark"] {
  /* 深色主题 */
  --color-primary: #5dade2;
  --color-primary-dark: #3498db;
  --color-secondary: #58d68d;
  --color-secondary-dark: #2ecc71;
  --color-background: #2c3e50;
  --color-text: #ecf0f1;
}

这个 CSS 文件定义了我们的浅色和深色主题的变量。通过使用 CSS 变量,我们可以轻松地在不同主题之间切换。

  1. 实现主题切换功能

创建一个新文件 src/ThemeToggle.tsx

import React, { useState, useEffect } from 'react';
 
const ThemeToggle: React.FC = () => {
  const [theme, setTheme] = useState(localStorage.getItem('theme') || 'light');
 
  const toggleTheme = () => {
    const newTheme = theme === 'light' ? 'dark' : 'light';
    setTheme(newTheme);
  };
 
  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme);
    localStorage.setItem('theme', theme);
  }, [theme]);
 
  return (
    <button onClick={toggleTheme} className="btn-primary">
      切换主题
    </button>
  );
};
 
export default ThemeToggle;

这个组件管理主题切换并将用户的选择保存在 localStorage 中。它使用 React 的 hooks 来管理状态和副作用。

  1. 创建一个使用主题的组件

让我们创建一个 Card 组件。新建一个文件 src/Card.tsx

import React from 'react';
 
interface CardProps {
  title: string;
  content: string;
}
 
const Card: React.FC<CardProps> = ({ title, content }) => {
  return (
    <div className="bg-background text-text p-4 rounded-lg shadow-md custom-transition">
      <h2 className="text-primary text-xl font-sans mb-2">{title}</h2>
      <p className="text-secondary font-serif">{content}</p>
      <button className="btn-primary mt-4">阅读更多</button>
    </div>
  );
};
 
export default Card;

这个 Card 组件使用我们的主题变量和 UnoCSS 类来设置样式。它会根据当前主题自动调整外观。

  1. 更新主 App 组件

现在,让我们更新主 App 组件。打开 src/App.tsx 并替换其内容:

import React from 'react';
import ThemeToggle from './ThemeToggle';
import Card from './Card';
 
const App: React.FC = () => {
  const cards = [
    { id: 1, title: '卡片 1', content: '这是第一张卡片的内容。' },
    { id: 2, title: '卡片 2', content: '这是第二张卡片的内容。' },
    { id: 3, title: '卡片 3', content: '这是第三张卡片的内容。' },
  ];
 
  return (
    <div className="p-4">
      <h1 className="text-primary text-2xl font-sans mb-4">我的主题应用</h1>
      <ThemeToggle className="mb-4" />
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
        {cards.map(card => (
          <Card key={card.id} title={card.title} content={card.content} />
        ))}
      </div>
    </div>
  );
};
 
export default App;

这个 App 组件整合了我们的 ThemeToggle 和 Card 组件,展示了我们的主题系统的使用。

  1. 更新入口点

最后,我们需要更新我们的主入口点以包含我们的 CSS 文件。打开 src/index.tsx 并更新为:

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './themes.css';
import 'uno.css'; // 这是生成的UnoCSS文件
 
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
  1. 配置 Bun 以使用 UnoCSS

为了使 Bun 能够与 UnoCSS 一起工作,我们需要创建一个简单的构建脚本。在项目根目录创建一个名为 build.js 的文件:

import { build } from 'esbuild';
import { readFile, writeFile } from 'fs/promises';
import UnoCSS from 'unocss/vite';
 
// 构建项目
await build({
  entryPoints: ['src/index.tsx'],
  bundle: true,
  outfile: 'dist/bundle.js',
  plugins: [
    {
      name: 'unocss',
      setup(build) {
        build.onEnd(async () => {
          const unocss = UnoCSS();
          const { css } = await unocss.generateCSS();
          await writeFile('dist/uno.css', css);
        });
      },
    },
  ],
});
 
// 将index.html复制到dist目录
const html = await readFile('index.html', 'utf8');
await writeFile('dist/index.html', html);

这个脚本使用 esbuild(Bun 自带)来打包您的应用程序,并生成 UnoCSS 样式。

更新您的 package.json 以包含一个构建脚本:

{
  "scripts": {
    "dev": "bun run --hot src/index.tsx",
    "build": "bun run build.js"
  }
}

现在,您可以运行 bun run dev 进行开发,运行 bun run build 来构建您的项目。

这个设置创建了一个使用 Bun 作为运行时的 React 应用程序,实现了一个基于 UnoCSS 的主题系统。该系统允许轻松切换主题并在组件之间保持一致的样式。

一些需要记住的关键点:

  1. Bun 为 JavaScript 和 TypeScript 应用程序提供了出色的性能。
  2. React 的基于组件的架构与我们的主题方法很好地配合。
  3. UnoCSS 给了我们创建自定义设计系统的灵活性。
  4. CSS 变量允许我们轻松切换主题,而无需重新构建应用程序。
  5. 我们创建的构建脚本确保 UnoCSS 样式被生成并包含在最终构建中。

随着您进一步开发应用程序,您可能想要考虑:

  • 创建更多可重用的主题组件
  • 实现更复杂的主题配置
  • 添加尊重当前主题的动画
  • 创建一个主题配置面板,让用户自定义他们的体验

记住,这个系统是高度灵活的。随着应用程序的增长,您可以轻松扩展主题变量,添加新的 UnoCSS 规则,或创建更复杂的组件。Bun、React 和 UnoCSS 的组合为构建高性能、可主题化的 Web 应用程序提供了强大的基础。

希望这个中文解释能够帮助您更好地理解如何使用 Bun 和 React 实现 UnoCSS 的定制主题方案。如果您有任何进一步的问题或需要更详细的解释,请随时告诉我。