在本文中,我们将使用 React 创建一个简单的卡片组件,该组件可以根据用户的交互更改背景颜色和文字颜色。我们将使用 React 内联样式来管理卡片的样式,并通过 React 的 useState 钩子来管理状态。
创建 Card 组件
我们从创建一个名为 Card 的函数组件开始。该组件将渲染一个包含标题、段落和按钮的卡片。用户可以将鼠标悬停在按钮上,以更改卡片的样式。从 Card 组件顶部的 React 导入 useState。 导入后,我们将使用数组解构来创建状态变量和更新状态的函数。
card.jsx
import React, { useState } from "react";
const Card = () => {
// 使用 useState 定义状态变量和更新函数
const [style, setStyle] = useState({
background: "#fdfdfd",
color: "#424246"
});
// 定义一个函数,根据用户的交互更新卡片的样式
const setCardStyle = (background, color) => {
setStyle({ background, color });
};
// 定义卡片和按钮的样式
const cardStyle = {
maxWidth: "600px",
padding: "40px",
backgroundColor: style.background,
};
const headerStyle = {
fontSize: "36px",
marginBottom: "10px",
color: style.color
};
const paragraphStyle = {
fontSize: "16px",
marginBottom: "20px",
color: style.color
};
const buttonStyle = {
fontWeight: "500",
fontSize: "12px",
padding: "10px 30px",
marginRight: "20px",
marginBottom: "20px",
borderRadius: "50px",
cursor: "pointer"
};
const blackButtonStyle = {
...buttonStyle,
color: "#fdfdfd",
backgroundColor: "#424246"
};
const blueButtonStyle = {
...buttonStyle,
color: "#fdfdfd",
backgroundColor: "#1d499b"
};
const yellowButtonStyle = {
...buttonStyle,
color: "#424246",
backgroundColor: "#f9d648"
};
return (
<div style={cardStyle}>
<h1 style={headerStyle}>颜色卡片</h1>
<p style={paragraphStyle}>
通过鼠标移入按钮来更改卡片的背景颜色,移出后恢复
</p>
<div>
<div
onMouseEnter={() => setCardStyle("#424246", "#fdfdfd")}
onMouseOut={() => setCardStyle("#fdfdfd", "#424246")}
style={blackButtonStyle}
>
Black
</div>
<div
onMouseEnter={() => setCardStyle("#1d499b", "#fdfdfd")}
onMouseOut={() => setCardStyle("#fdfdfd", "#424246")}
style={blueButtonStyle}
>
Blue
</div>
<div
onMouseEnter={() => setCardStyle("#f9d648", "#424246")}
onMouseOut={() => setCardStyle("#fdfdfd", "#424246")}
style={yellowButtonStyle}
>
Yellow
</div>
</div>
</div>
);
};
export default Card;
在上述代码中,我们首先导入了 React 和 useState 钩子。然后,我们定义了一个名为 Card 的函数组件,其中包含了一个 useState 钩子来管理状态。useState 钩子返回一个状态变量和一个更新该变量的函数。我们使用这个函数来更新卡片的样式。 在组件内部,我们定义了一个 setCardStyle 函数,它接受两个参数:background 和 color。这个函数用来更新卡片的样式。然后,我们定义了卡片和按钮的样式对象,以及三种不同颜色的按钮样式。 最后,我们返回一个包含标题、段落和按钮的 div 元素。当用户将鼠标悬停在按钮上时,会触发相应的 onMouseEnter 和 onMouseOut 事件处理函数,从而更新卡片的样式。
Emotion库的使用
Emotion是一种CSS in JS的 React 应用中写样式的一个主流的方案,一些基本的使用方法可以访问官网地址: emotion.sh/docs/introd... Emotion的的优点如下:
- 不用关心繁琐的 Class 命名规则
- 不用担心样式被覆盖
- 便利的样式复用(样式都是 js 对象或字符串)
- 减少冗余的 CSS 代码,极致的样式按需加载
通过Emotion实现Card的组件:
card.jsx
/** @jsxImportSource @emotion/react */
import React, { useState } from "react";
import { jsx, css } from '@emotion/react'
const Card = () => {
// 使用 useState 定义状态变量和更新函数
const [style, setStyle] = useState({
background: "#fdfdfd",
color: "#424246"
});
// 定义一个函数,根据用户的交互更新卡片的样式
const setCardStyle = (background, color) => {
setStyle({ background, color });
};
const card = css`
max-width: 600px;
padding: 40px 40px 20px 40px;
background-color: ${style.background};
h1 {
font-weight: 400;
font-size: 36px;
margin-bottom: 10px;
color: ${style.color};
}
p {
font-weight: 300;
font-size: 16px;
margin-bottom: 20px;
color: ${style.color};
}
`;
const cardButtons = css`
display: flex;
flex-wrap: wrap;
div {
font-weight: 500;
font-size: 12px;
padding: 10px 30px;
margin-right: 20px;
margin-bottom: 20px;
border: none;
border-radius: 50px;
cursor: pointer;
}
`;
const blackButton = css`
color: #fdfdfd;
background-color: #424246;
`;
const blueButton = css`
color: #fdfdfd;
background-color: #1d499b;
`;
const yellowButton = css`
color: #424246;
background-color: #f9d648;
`;
return (
<div css={card}>
<h1>颜色卡片</h1>
<p>通过鼠标移入按钮来更改卡片的背景颜色,移出后恢复</p>
<div css={cardButtons}>
<div
onMouseEnter={() => setCardStyle("#424246", "#fdfdfd")}
onMouseOut={() => setCardStyle("#fdfdfd", "#424246")}
css={blackButton}
>
Black
</div>
<div
onMouseEnter={() => setCardStyle("#1d499b", "#fdfdfd")}
onMouseOut={() => setCardStyle("#fdfdfd", "#424246")}
css={blueButton}
>
Blue
</div>
<div
onMouseEnter={() => setCardStyle("#f9d648", "#424246")}
onMouseOut={() => setCardStyle("#fdfdfd", "#424246")}
css={yellowButton}
>
Yellow
</div>
</div>
</div>
);
}
export default Card;
需要注意的是,将 jsx 注释
设置在使用道具的源文件的顶部。 此选项最适合测试 prop 功能或在 babel 配置不可配置的项目(create-react-app、codesandbox 等)中。
js
/** @jsxImportSource @emotion/react */
import { jsx } from '@emotion/react'
/** @jsxImportSource @emotion/react */
不生效的时候可以改为 /** @jsx jsx */
来尝试。
自定义改变全局的主题
当我们使用 Emotion 库创建 React 组件时,通常希望能够轻松地管理全局的主题,以便在整个应用程序中共享样式和颜色。
创建自定义主题的组件:ThemeProvider
ThemeProvider.jsx
/** @jsxImportSource @emotion/react */
import { createContext, useContext, useState, useEffect } from 'react';
import { ThemeProvider as EmotionThemeProvider } from '@emotion/react';
import { lightTheme, darkTheme } from '../themes'; // 假设你有两个主题文件
const ThemeContext = createContext();
export const customUseTheme = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
};
const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light'); // 默认主题为 light
useEffect(() => {
// 通过 localStorage 或其他途径保存当前主题设置
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
setTheme(savedTheme);
}
}, []);
useEffect(() => {
// 每次主题改变时更新 localStorage 中的值
localStorage.setItem('theme', theme);
}, [theme]);
const toggleTheme = () => {
setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
};
const themeValues = {
theme,
toggleTheme,
};
return (
<ThemeContext.Provider value={themeValues}>
<EmotionThemeProvider theme={theme === 'light' ? lightTheme : darkTheme}>
{children}
</EmotionThemeProvider>
</ThemeContext.Provider>
);
};
export default ThemeProvider;
根组件中引入
app.jsx
import React from 'react';
import ThemeProvider from './components/ThemeProvider';
import Card from './components/card';
function App() {
return (
<ThemeProvider>
<Card />
</ThemeProvider>
)
}
export default App
card组件中的使用:
card.jsx
/** @jsxImportSource @emotion/react */
import { jsx, css, useTheme } from '@emotion/react';
import { customUseTheme } from './ThemeProvider';
function Card() {
const theme = useTheme();
const { toggleTheme } = customUseTheme();
const card = css`
max-width: 600px;
padding: 40px 40px 20px 40px;
background-color: ${theme.colors.background};
h1 {
font-weight: 400;
font-size: 36px;
margin-bottom: 10px;
color: ${theme.colors.primary};
}
p {
font-weight: 300;
font-size: 16px;
margin-bottom: 20px;
color: ${theme.colors.primary};
}
`;
return (
<div css={card}>
<h1>颜色卡片</h1>
<p>通过鼠标移入按钮来更改卡片的背景颜色,移出后恢复</p>
<button onClick={toggleTheme}>Toggle Theme</button>
</div>
);
}
export default Card