React案例:鼠标移入和移出更改背景颜色

在本文中,我们将使用 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的的优点如下:

  1. 不用关心繁琐的 Class 命名规则
  2. 不用担心样式被覆盖
  3. 便利的样式复用(样式都是 js 对象或字符串)
  4. 减少冗余的 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
相关推荐
定栓5 小时前
Webpack迁到Vite第一节:模块系统迁移:require → import
运维·前端·webpack
小熊在忙fpga5 小时前
N32G430芯片的flash表示
前端·javascript·html
Data analyse4565 小时前
App埋点版本兼容的字段迁移校验
大数据·运维·服务器·前端·数据库·数据分析
todoitbo5 小时前
本来只想给内网开个口子,Natapp 却多给了一道防护
前端·javascript·vue.js·内网穿透·网络防护·natapp
会灭火的程序员5 小时前
SuperMap AgentX Server智能体接入WEB应用技术文档
前端·supermap·agentx·agentx server
CRMEB5 小时前
商品 SKU 设计,从简单规格到多规格踩过什么
java·前端·数据库·开源
Chloe.Zz5 小时前
一篇入门Agent
开发语言·前端·javascript
java1234_小锋5 小时前
【技术专题】HTML5 网页技术 - HTML5 表格标签
前端·html·html5
雪芽蓝域zzs6 小时前
JS 项目转 TS 项目(Vue3 + 若依这类后台项目)完整改造清单
前端·vue.js