下面是在主题切换示例中添加样式切换动画的实现,通过 CSS 过渡(transition
)和动态类名实现平滑的主题切换效果:
import { createContext, useContext, useState, useMemo } from 'react';
import './ThemeExample.css'; // 引入样式文件
// 1. 创建主题Context
const ThemeContext = createContext({
theme: 'light',
toggleTheme: () => {}
});
// 2. 主题Provider组件
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
// 切换主题方法
const toggleTheme = () => {
setTheme(prev => prev === 'light' ? 'dark' : 'light');
};
// 缓存主题数据,避免不必要的重渲染
const value = useMemo(() => ({
theme,
toggleTheme
}), [theme]);
return (
<ThemeContext.Provider value={value}>
{/* 给根元素添加主题类名,用于全局样式切换 */}
<div className={`theme-container theme-${theme}`}>
{children}
</div>
</ThemeContext.Provider>
);
}
// 3. 自定义Hook
export function useTheme() {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
}
// 4. 主题切换按钮组件
function ThemeToggleButton() {
const { theme, toggleTheme } = useTheme();
return (
<button className="theme-toggle-btn" onClick={toggleTheme}>
当前主题:{theme === 'light' ? '浅色' : '深色'}(点击切换)
</button>
);
}
// 5. 示例内容组件(展示动画效果)
function ThemeContent() {
return (
<div className="theme-content">
<h2>主题切换动画示例</h2>
<p>这是一段测试文本,会随主题变化颜色</p>
<div className="theme-card">
<p>卡片内容</p>
</div>
</div>
);
}
// 6. 根组件
function App() {
return (
<ThemeProvider>
<div className="app">
<ThemeToggleButton />
<ThemeContent />
</div>
</ThemeProvider>
);
}
export default App;
配套的 CSS 文件(ThemeExample.css
):
/* 基础样式 */
.theme-container {
min-height: 100vh;
transition: background-color 0.5s ease, color 0.5s ease;
padding: 20px;
}
/* 浅色主题 */
.theme-light {
background-color: #ffffff;
color: #333333;
}
/* 深色主题 */
.theme-dark {
background-color: #2c3e50;
color: #ecf0f1;
}
/* 按钮样式 */
.theme-toggle-btn {
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
transition: all 0.3s ease; /* 按钮自身的过渡动画 */
}
/* 浅色主题下的按钮 */
.theme-light .theme-toggle-btn {
background-color: #3498db;
color: white;
}
/* 深色主题下的按钮 */
.theme-dark .theme-toggle-btn {
background-color: #e74c3c;
color: white;
}
/* 按钮悬停效果 */
.theme-toggle-btn:hover {
transform: scale(1.05);
}
/* 内容区域样式 */
.theme-content {
margin-top: 30px;
transition: all 0.5s ease; /* 内容区域的过渡动画 */
}
/* 卡片样式 */
.theme-card {
margin-top: 20px;
padding: 20px;
border-radius: 8px;
transition: all 0.5s ease; /* 卡片的过渡动画 */
}
/* 浅色主题下的卡片 */
.theme-light .theme-card {
background-color: #f8f9fa;
border: 1px solid #dee2e6;
}
/* 深色主题下的卡片 */
.theme-dark .theme-card {
background-color: #34495e;
border: 1px solid #2c3e50;
}
/* 标题动画 */
.theme-content h2 {
transition: transform 0.5s ease, color 0.5s ease;
}
.theme-dark .theme-content h2 {
transform: translateY(5px);
}
theme-container
)上添加了 background-color
和 color
的过渡动画(0.5秒),实现背景色和文字色的平滑切换transition
属性,确保样式变化时的连贯性transform: scale(1.05)
),增强交互感translateY(5px)
),增加层次感theme-light
或 theme-dark
类名,所有子元素通过后代选择器适配不同主题transition
而非 animation
:对于样式切换场景,transition
更简洁,适合处理"从A状态到B状态"的变化useMemo
缓存主题数据,避免 Provider 重新渲染时不必要的子组件更新这种实现方式既保证了动画的流畅性,又保持了代码的可维护性,适合在实际项目中使用。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。