React 样式语法知识点与案例详解

作为React初学者,掌握样式语法是构建美观UI的关键。本文将详细介绍React中所有主要的样式方法,并提供详细注释的案例代码。

一、React样式语法知识点总览

1. 行内样式 (Inline Styles)

  • 使用style属性,值为JavaScript对象
  • 属性名采用驼峰命名法
  • 值为字符串或数字

2. CSS样式表 (CSS Stylesheets)

  • 传统的CSS文件引入方式
  • 使用className而非class

3. CSS Modules

  • 局部作用域的CSS
  • 避免样式冲突
  • 文件名通常为[name].module.css

4. CSS-in-JS库 (Styled-components)

  • 在JavaScript中编写CSS
  • 动态样式支持良好
  • 组件即样式

5. 使用Sass/SCSS预处理器

  • 支持变量、嵌套、混合等功能
  • 文件扩展名为.scss.sass

6. 使用Tailwind CSS

  • 实用优先的CSS框架
  • 直接在className中使用实用类

7. 条件样式

  • 根据状态或props动态应用样式
  • 使用三元运算符或逻辑运算符

8. 动态样式

  • 根据数据或用户交互改变样式
  • 结合状态管理使用

二、详细案例代码

案例1:行内样式 (Inline Styles)

import React, { useState } from 'react';function InlineStyleExample() {// 定义样式对象 - 注意驼峰命名法const containerStyle = {padding: '20px',backgroundColor: '#f0f0f0',borderRadius: '8px',margin: '10px 0',fontFamily: 'Arial, sans-serif'};const buttonStyle = {backgroundColor: '#007bff',color: 'white',border: 'none',padding: '10px 20px',borderRadius: '4px',cursor: 'pointer',fontSize: '16px',marginRight: '10px'};const hoverButtonStyle = {...buttonStyle, // 使用展开运算符继承基础样式backgroundColor: '#0056b3', // 覆盖背景色transform: 'scale(1.05)', // 添加缩放效果transition: 'all 0.3s ease' // 添加过渡效果};// 状态管理用于动态样式const [isHovered, setIsHovered] = useState(false);const [fontSize, setFontSize] = useState(16);return (<div style={containerStyle}><h2 style={{ color: '#333', marginBottom: '20px',textAlign: 'center'}}>行内样式示例</h2>{/* 基础按钮样式 */}<button style={buttonStyle}onMouseEnter={() => setIsHovered(true)}onMouseLeave={() => setIsHovered(false)}>基础按钮</button>{/* 动态按钮样式 - 根据hover状态改变 */}<button style={isHovered ? hoverButtonStyle : buttonStyle}>{isHovered ? '鼠标悬停中' : '悬停我'}</button>{/* 根据状态动态改变字体大小 */}<div style={{ marginTop: '20px' }}><p style={{ fontSize: `${fontSize}px`,transition: 'font-size 0.3s ease'}}>当前字体大小: {fontSize}px</p><button style={buttonStyle}onClick={() => setFontSize(prev => Math.min(prev + 2, 32))}>增大字体</button><button style={buttonStyle}onClick={() => setFontSize(prev => Math.max(prev - 2, 12))}>减小字体</button></div>{/* 复杂的动态样式示例 */}<div style={{marginTop: '30px',padding: '15px',backgroundColor: isHovered ? '#e9ecef' : '#ffffff',border: `2px solid ${isHovered ? '#007bff' : '#dee2e6'}`,borderRadius: '8px',transition: 'all 0.3s ease',cursor: 'pointer'}} onMouseEnter={() => setIsHovered(true)}onMouseLeave={() => setIsHovered(false)}><p>这个盒子的样式会根据鼠标悬停状态动态改变</p><p style={{ fontStyle: 'italic', color: '#6c757d' }}>{isHovered ? '鼠标正在悬停' : '请将鼠标悬停在此处'}</p></div></div>);
}export default InlineStyleExample;

案例2:CSS样式表 (CSS Stylesheets)

首先创建 StylesheetExample.css 文件:

/* StylesheetExample.css */
.card-container {padding: 20px;background-color: #f8f9fa;border-radius: 8px;margin: 20px 0;box-shadow: 0 2px 4px rgba(0,0,0,0.1);font-family: 'Arial', sans-serif;
}.card-title {color: #343a40;font-size: 24px;margin-bottom: 15px;text-align: center;border-bottom: 2px solid #007bff;padding-bottom: 10px;
}.card-content {background-color: white;padding: 15px;border-radius: 4px;margin: 15px 0;box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}.button-group {display: flex;justify-content: center;gap: 10px;margin-top: 20px;
}.btn {padding: 10px 20px;border: none;border-radius: 4px;cursor: pointer;font-size: 16px;transition: all 0.3s ease;
}.btn-primary {background-color: #007bff;color: white;
}.btn-primary:hover {background-color: #0056b3;transform: translateY(-2px);
}.btn-secondary {background-color: #6c757d;color: white;
}.btn-secondary:hover {background-color: #545b62;transform: translateY(-2px);
}.alert-box {padding: 15px;margin: 15px 0;border-radius: 4px;font-weight: bold;
}.alert-success {background-color: #d4edda;color: #155724;border: 1px solid #c3e6cb;
}.alert-danger {background-color: #f8d7da;color: #721c24;border: 1px solid #f5c6cb;
}/* 响应式设计 */
@media (max-width: 768px) {.card-container {padding: 15px;margin: 10px 0;}.button-group {flex-direction: column;align-items: center;}.btn {width: 100%;max-width: 200px;}
}

然后创建 React 组件:

import React, { useState } from 'react';
import './StylesheetExample.css'; // 导入CSS文件function StylesheetExample() {const [message, setMessage] = useState('');const [messageType, setMessageType] = useState('');const [count, setCount] = useState(0);const handlePrimaryClick = () => {setCount(count + 1);setMessage(`点击了 ${count + 1} 次主按钮`);setMessageType('success');};const handleSecondaryClick = () => {setCount(count - 1);setMessage(`点击了 ${count - 1} 次次按钮`);setMessageType('danger');};const resetCount = () => {setCount(0);setMessage('计数器已重置');setMessageType('success');};return (<div className="card-container"><h2 className="card-title">CSS样式表示例</h2><div className="card-content"><p>当前计数: <strong>{count}</strong></p>{/* 条件渲染alert消息 */}{message && (<div className={`alert-box alert-${messageType}`}>{message}</div>)}<div className="button-group"><button className="btn btn-primary" onClick={handlePrimaryClick}>主按钮 (+1)</button><button className="btn btn-secondary" onClick={handleSecondaryClick}>次按钮 (-1)</button><button className="btn btn-secondary" onClick={resetCount}>重置</button></div></div>{/* 条件样式示例 */}<div className="card-content"><h3>条件样式示例</h3><p>根据计数值改变样式:</p><div className="alert-box" style={{ backgroundColor: count > 0 ? '#d4edda' : count < 0 ? '#f8d7da' : '#fff3cd',color: count > 0 ? '#155724' : count < 0 ? '#721c24' : '#856404',border: count > 0 ? '1px solid #c3e6cb' : count < 0 ? '1px solid #f5c6cb' : '1px solid #ffeaa7'}}>{count > 0 ? '正数状态' : count < 0 ? '负数状态' : '零状态'}</div></div></div>);
}export default StylesheetExample;

案例3:CSS Modules

首先创建 CSSModulesExample.module.css 文件:

/* CSSModulesExample.module.css */
.container {padding: 20px;background-color: #e9ecef;border-radius: 8px;margin: 20px 0;font-family: 'Arial', sans-serif;
}.title {color: #28a745;font-size: 24px;margin-bottom: 15px;text-align: center;border-bottom: 2px solid #28a745;padding-bottom: 10px;
}.contentBox {background-color: white;padding: 20px;border-radius: 6px;margin: 15px 0;box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}.buttonContainer {display: flex;justify-content: space-around;flex-wrap: wrap;gap: 10px;margin-top: 20px;
}.primaryBtn {padding: 12px 24px;background-color: #28a745;color: white;border: none;border-radius: 4px;cursor: pointer;font-size: 16px;transition: all 0.3s ease;
}.primaryBtn:hover {background-color: #218838;transform: scale(1.05);
}.dangerBtn {padding: 12px 24px;background-color: #dc3545;color: white;border: none;border-radius: 4px;cursor: pointer;font-size: 16px;transition: all 0.3s ease;
}.dangerBtn:hover {background-color: #c82333;transform: scale(1.05);
}.infoBox {padding: 15px;margin: 15px 0;border-radius: 4px;font-weight: 500;
}.info {composes: infoBox;background-color: #cce5ff;color: #004085;border: 1px solid #b8daff;
}.warning {composes: infoBox;background-color: #fff3cd;color: #856404;border: 1px solid #ffeaa7;
}.success {composes: infoBox;background-color: #d4edda;color: #155724;border: 1px solid #c3e6cb;
}/* 动画效果 */
@keyframes fadeIn {from { opacity: 0; transform: translateY(10px); }to { opacity: 1; transform: translateY(0); }
}.animatedBox {animation: fadeIn 0.5s ease-out;
}/* 响应式设计 */
@media (max-width: 768px) {.container {padding: 15px;margin: 10px 0;}.buttonContainer {flex-direction: column;align-items: center;}.primaryBtn, .dangerBtn {width: 100%;max-width: 250px;}
}

然后创建 React 组件:

import React, { useState, useEffect } from 'react';
import styles from './CSSModulesExample.module.css'; // 导入CSS Modulesfunction CSSModulesExample() {const [count, setCount] = useState(0);const [showMessage, setShowMessage] = useState(false);const [messageType, setMessageType] = useState('info');const [isVisible, setIsVisible] = useState(true);// 模拟组件加载时的动画效果useEffect(() => {const timer = setTimeout(() => {setShowMessage(true);}, 500);return () => clearTimeout(timer);}, []);const increment = () => {setCount(count + 1);setMessageType('success');setShowMessage(true);// 3秒后隐藏消息setTimeout(() => setShowMessage(false), 3000);};const decrement = () => {setCount(count - 1);setMessageType('warning');setShowMessage(true);setTimeout(() => setShowMessage(false), 3000);};const reset = () => {setCount(0);setMessageType('info');setShowMessage(true);setTimeout(() => setShowMessage(false), 3000);};const toggleVisibility = () => {setIsVisible(!isVisible);};// 根据计数值动态选择样式const getDynamicStyle = () => {if (count > 0) return styles.success;if (count < 0) return styles.warning;return styles.info;};return (<div className={styles.container}><h2 className={styles.title}>CSS Modules 示例</h2>{/* 可切换可见性的内容框 */}{isVisible && (<div className={`${styles.contentBox} ${styles.animatedBox}`}><h3>计数器</h3><p>当前值: <strong>{count}</strong></p>{/* 条件渲染的消息框 */}{showMessage && (<div className={styles[messageType]}>{messageType === 'success' && `增加了1,现在是 ${count}`}{messageType === 'warning' && `减少了1,现在是 ${count}`}{messageType === 'info' && `已重置为 ${count}`}</div>)}<div className={styles.buttonContainer}><button className={styles.primaryBtn} onClick={increment}>增加 (+1)</button><button className={styles.dangerBtn} onClick={decrement}>减少 (-1)</button><button className={styles.primaryBtn} onClick={reset}>重置</button></div></div>)}{/* 动态样式示例 */}<div className={styles.contentBox}><h3>动态样式示例</h3><div className={getDynamicStyle()}>{count > 0 ? '正数状态 - 成功样式' : count < 0 ? '负数状态 - 警告样式' : '零状态 - 信息样式'}</div></div>{/* 控制组件可见性的按钮 */}<div className={styles.buttonContainer}><button className={isVisible ? styles.dangerBtn : styles.primaryBtn}onClick={toggleVisibility}>{isVisible ? '隐藏内容' : '显示内容'}</button></div></div>);
}export default CSSModulesExample;

案例4:Styled-components

首先安装 styled-components:

npm install styled-components

然后创建组件:

import React, { useState } from 'react';
import styled, { keyframes, css } from 'styled-components';// 定义动画
const fadeIn = keyframes`from {opacity: 0;transform: translateY(20px);}to {opacity: 1;transform: translateY(0);}
`;// 定义基础容器样式
const Container = styled.div`padding: 20px;background-color: ${props => props.theme.backgroundColor || '#f8f9fa'};border-radius: 8px;margin: 20px 0;box-shadow: 0 2px 10px rgba(0,0,0,0.1);font-family: 'Arial', sans-serif;animation: ${fadeIn} 0.6s ease-out;
`;// 标题样式
const Title = styled.h2`color: ${props => props.theme.titleColor || '#343a40'};font-size: 24px;margin-bottom: 15px;text-align: center;border-bottom: 2px solid ${props => props.theme.accentColor || '#007bff'};padding-bottom: 10px;position: relative;&::after {content: '';position: absolute;bottom: -2px;left: 50%;width: 60px;height: 2px;background-color: ${props => props.theme.accentColor || '#007bff'};transform: translateX(-50%);}
`;// 内容框样式
const ContentBox = styled.div`background-color: white;padding: 20px;border-radius: 6px;margin: 15px 0;box-shadow: 0 2px 8px rgba(0,0,0,0.05);transition: all 0.3s ease;&:hover {box-shadow: 0 4px 15px rgba(0,0,0,0.1);transform: translateY(-2px);}
`;// 按钮组容器
const ButtonGroup = styled.div`display: flex;justify-content: center;flex-wrap: wrap;gap: 10px;margin-top: 20px;
`;// 基础按钮样式
const BaseButton = styled.button`padding: 12px 24px;border: none;border-radius: 4px;cursor: pointer;font-size: 16px;font-weight: 500;transition: all 0.3s ease;position: relative;overflow: hidden;&:before {content: '';position: absolute;top: 0;left: -100%;width: 100%;height: 100%;background: rgba(255,255,255,0.2);transition: all 0.5s ease;}&:hover:before {left: 100%;}&:hover {transform: translateY(-2px) scale(1.03);box-shadow: 0 4px 15px rgba(0,0,0,0.2);}&:active {transform: translateY(0) scale(0.98);}
`;// 主按钮样式 - 扩展BaseButton
const PrimaryButton = styled(BaseButton)`background-color: ${props => props.theme.primaryColor || '#007bff'};color: white;&:hover {background-color: ${props => props.theme.primaryHoverColor || '#0056b3'};}
`;// 危险按钮样式 - 扩展BaseButton
const DangerButton = styled(BaseButton)`background-color: ${props => props.theme.dangerColor || '#dc3545'};color: white;&:hover {background-color: ${props => props.theme.dangerHoverColor || '#c82333'};}
`;// 信息框样式 - 根据类型动态变化
const InfoBox = styled.div`padding: 15px;margin: 15px 0;border-radius: 4px;font-weight: 500;text-align: center;animation: ${fadeIn} 0.4s ease-out;${props => props.type === 'success' && css`background-color: #d4edda;color: #155724;border: 1px solid #c3e6cb;border-left: 5px solid #28a745;`}${props => props.type === 'warning' && css`background-color: #fff3cd;color: #856404;border: 1px solid #ffeaa7;border-left: 5px solid #ffc107;`}${props => props.type === 'danger' && css`background-color: #f8d7da;color: #721c24;border: 1px solid #f5c6cb;border-left: 5px solid #dc3545;`}${props => props.type === 'info' && css`background-color: #cce5ff;color: #004085;border: 1px solid #b8daff;border-left: 5px solid #17a2b8;`}
`;// 主题配置
const theme = {backgroundColor: '#f8f9fa',titleColor: '#2c3e50',accentColor: '#3498db',primaryColor: '#3498db',primaryHoverColor: '#2980b9',dangerColor: '#e74c3c',dangerHoverColor: '#c0392b'
};function StyledComponentsExample() {const [count, setCount] = useState(0);const [showMessage, setShowMessage] = useState(false);const [messageType, setMessageType] = useState('info');const [themeMode, setThemeMode] = useState('light');// 切换主题const toggleTheme = () => {setThemeMode(themeMode === 'light' ? 'dark' : 'light');};// 自定义暗色主题const darkTheme = {backgroundColor: '#2c3e50',titleColor: '#ecf0f1',accentColor: '#3498db',primaryColor: '#3498db',primaryHoverColor: '#2980b9',dangerColor: '#e74c3c',dangerHoverColor: '#c0392b'};const currentTheme = themeMode === 'dark' ? darkTheme : theme;const increment = () => {setCount(count + 1);setMessageType('success');setShowMessage(true);setTimeout(() => setShowMessage(false), 3000);};const decrement = () => {setCount(count - 1);setMessageType('warning');setShowMessage(true);setTimeout(() => setShowMessage(false), 3000);};const reset = () => {setCount(0);setMessageType('info');setShowMessage(true);setTimeout(() => setShowMessage(false), 3000);};return (<Container theme={currentTheme}><Title theme={currentTheme}>Styled-components 示例</Title><ContentBox><h3 style={{ color: currentTheme.titleColor, textAlign: 'center' }}>计数器: {count}</h3>{/* 条件渲染的消息框 */}{showMessage && (<InfoBox type={messageType}>{messageType === 'success' && `计数器增加到 ${count}`}{messageType === 'warning' && `计数器减少到 ${count}`}{messageType === 'info' && `计数器重置为 ${count}`}</InfoBox>)}<ButtonGroup><PrimaryButton onClick={increment}>增加 (+1)</PrimaryButton><DangerButton onClick={decrement}>减少 (-1)</DangerButton><PrimaryButton onClick={reset}>重置</PrimaryButton></ButtonGroup></ContentBox>{/* 主题切换示例 */}<ContentBox><h3 style={{ color: currentTheme.titleColor, textAlign: 'center' }}>主题: {themeMode === 'light' ? '浅色模式' : '深色模式'}</h3><ButtonGroup><PrimaryButton onClick={toggleTheme}>切换到 {themeMode === 'light' ? '深色' : '浅色'} 模式</PrimaryButton></ButtonGroup></ContentBox>{/* 动态样式示例 */}<ContentBox><h3 style={{ color: currentTheme.titleColor, textAlign: 'center' }}>动态样式示例</h3><InfoBox type={count > 0 ? 'success' : count < 0 ? 'danger' : 'info'}>{count > 0 ? '正数 - 成功样式' : count < 0 ? '负数 - 危险样式' : '零 - 信息样式'}</InfoBox></ContentBox></Container>);
}// 包装组件以应用主题
const ThemedStyledComponentsExample = () => (<StyledComponentsExample />
);export default ThemedStyledComponentsExample;

案例5:Sass/SCSS 集成

首先安装 node-sass 或 sass:

npm install sass

创建 SassExample.scss 文件:

// SassExample.scss
// 定义变量
$primary-color: #007bff;
$secondary-color: #6c757d;
$success-color: #28a745;
$danger-color: #dc3545;
$warning-color: #ffc107;
$info-color: #17a2b8;$border-radius: 8px;
$box-shadow: 0 2px 10px rgba(0,0,0,0.1);// 混合
@mixin button-style($bg-color, $hover-color) {padding: 12px 24px;background-color: $bg-color;color: white;border: none;border-radius: 4px;cursor: pointer;font-size: 16px;font-weight: 500;transition: all 0.3s ease;&:hover {background-color: $hover-color;transform: translateY(-2px) scale(1.03);box-shadow: 0 4px 15px rgba(0,0,0,0.2);}&:active {transform: translateY(0) scale(0.98);}
}// 容器样式
.sass-container {padding: 20px;background-color: #f8f9fa;border-radius: $border-radius;margin: 20px 0;box-shadow: $box-shadow;font-family: 'Arial', sans-serif;// 嵌套样式.title {color: #343a40;font-size: 24px;margin-bottom: 15px;text-align: center;border-bottom: 2px solid $primary-color;padding-bottom: 10px;position: relative;&::after {content: '';position: absolute;bottom: -2px;left: 50%;width: 60px;height: 2px;background-color: $primary-color;transform: translateX(-50%);}}
}// 内容框
.sass-content-box {background-color: white;padding: 20px;border-radius: 6px;margin: 15px 0;box-shadow: 0 2px 8px rgba(0,0,0,0.05);transition: all 0.3s ease;&:hover {box-shadow: 0 4px 15px rgba(0,0,0,0.1);transform: translateY(-2px);}// 嵌套的标题h3 {color: #343a40;text-align: center;margin-bottom: 15px;}
}// 按钮组
.sass-button-group {display: flex;justify-content: center;flex-wrap: wrap;gap: 10px;margin-top: 20px;
}// 使用混合定义按钮
.sass-primary-btn {@include button-style($primary-color, darken($primary-color, 10%));
}.sass-success-btn {@include button-style($success-color, darken($success-color, 10%));
}.sass-danger-btn {@include button-style($danger-color, darken($danger-color, 10%));
}.sass-warning-btn {@include button-style($warning-color, darken($warning-color, 10%));color: #212529; // 警告按钮文字颜色
}// 信息框
.sass-info-box {padding: 15px;margin: 15px 0;border-radius: 4px;font-weight: 500;text-align: center;&.success {background-color: lighten($success-color, 40%);color: darken($success-color, 20%);border: 1px solid lighten($success-color, 30%);border-left: 5px solid $success-color;}&.warning {background-color: lighten($warning-color, 40%);color: darken($warning-color, 20%);border: 1px solid lighten($warning-color, 30%);border-left: 5px solid $warning-color;}&.danger {background-color: lighten($danger-color, 40%);color: darken($danger-color, 20%);border: 1px solid lighten($danger-color, 30%);border-left: 5px solid $danger-color;}&.info {background-color: lighten($info-color, 40%);color: darken($info-color, 20%);border: 1px solid lighten($info-color, 30%);border-left: 5px solid $info-color;}
}// 响应式设计
@media (max-width: 768px) {.sass-container {padding: 15px;margin: 10px 0;}.sass-button-group {flex-direction: column;align-items: center;}.sass-primary-btn, .sass-success-btn, .sass-danger-btn, .sass-warning-btn {width: 100%;max-width: 250px;}
}// 暗色主题
.dark-theme {.sass-container {background-color: #2c3e50;.title {color: #ecf0f1;border-bottom-color: $info-color;&::after {background-color: $info-color;}}}.sass-content-box {background-color: #34495e;h3 {color: #ecf0f1;}}
}

创建 React 组件:

import React, { useState } from 'react';
import './SassExample.scss'; // 导入SCSS文件function SassExample() {const [count, setCount] = useState(0);const [showMessage, setShowMessage] = useState(false);const [messageType, setMessageType] = useState('info');const [theme, setTheme] = useState('light');const increment = () => {setCount(count + 1);setMessageType('success');setShowMessage(true);setTimeout(() => setShowMessage(false), 3000);};const decrement = () => {setCount(count - 1);setMessageType('warning');setShowMessage(true);setTimeout(() => setShowMessage(false), 3000);};const reset = () => {setCount(0);setMessageType('info');setShowMessage(true);setTimeout(() => setShowMessage(false), 3000);};const toggleTheme = () => {setTheme(theme === 'light' ? 'dark' : 'light');};return (<div className={`sass-container ${theme === 'dark' ? 'dark-theme' : ''}`}><h2 className="title">Sass/SCSS 示例</h2><div className="sass-content-box"><h3>计数器: {count}</h3>{/* 条件渲染的消息框 */}{showMessage && (<div className={`sass-info-box ${messageType}`}>{messageType === 'success' && `计数器增加到 ${count}`}{messageType === 'warning' && `计数器减少到 ${count}`}{messageType === 'info' && `计数器重置为 ${count}`}</div>)}<div className="sass-button-group"><button className="sass-primary-btn" onClick={increment}>增加 (+1)</button><button className="sass-danger-btn" onClick={decrement}>减少 (-1)</button><button className="sass-success-btn" onClick={reset}>重置</button></div></div>{/* 主题切换 */}<div className="sass-content-box"><h3>当前主题: {theme === 'light' ? '浅色模式' : '深色模式'}</h3><div className="sass-button-group"><button className="sass-warning-btn" onClick={toggleTheme}>切换到 {theme === 'light' ? '深色' : '浅色'} 模式</button></div></div>{/* 动态样式示例 */}<div className="sass-content-box"><h3>动态样式示例</h3><div className={`sass-info-box ${count > 0 ? 'success' : count < 0 ? 'danger' : 'info'}`}>{count > 0 ? '正数 - 成功样式' : count < 0 ? '负数 - 危险样式' : '零 - 信息样式'}</div></div></div>);
}export default SassExample;

案例6:Tailwind CSS

首先安装 Tailwind CSS:

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

配置 tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {content: ["./src/**/*.{js,jsx,ts,tsx}",],theme: {extend: {},},plugins: [],
}

src/index.css 中添加:

@tailwind base;
@tailwind components;
@tailwind utilities;

创建组件:

import React, { useState } from 'react';function TailwindExample() {const [count, setCount] = useState(0);const [showMessage, setShowMessage] = useState(false);const [messageType, setMessageType] = useState('info');const [darkMode, setDarkMode] = useState(false);const increment = () => {setCount(count + 1);setMessageType('success');setShowMessage(true);setTimeout(() => setShowMessage(false), 3000);};const decrement = () => {setCount(count - 1);setMessageType('warning');setShowMessage(true);setTimeout(() => setShowMessage(false), 3000);};const reset = () => {setCount(0);setMessageType('info');setShowMessage(true);setTimeout(() => setShowMessage(false), 3000);};const toggleDarkMode = () => {setDarkMode(!darkMode);};// 根据消息类型返回相应的Tailwind CSS类const getMessageClasses = () => {switch (messageType) {case 'success':return 'bg-green-100 border border-green-400 text-green-700';case 'warning':return 'bg-yellow-100 border border-yellow-400 text-yellow-700';case 'danger':return 'bg-red-100 border border-red-400 text-red-700';case 'info':return 'bg-blue-100 border border-blue-400 text-blue-700';default:return 'bg-gray-100 border border-gray-400 text-gray-700';}};// 根据计数值返回相应的动态样式const getDynamicClasses = () => {if (count > 0) return 'bg-green-100 border-l-4 border-green-500 text-green-700';if (count < 0) return 'bg-red-100 border-l-4 border-red-500 text-red-700';return 'bg-blue-100 border-l-4 border-blue-500 text-blue-700';};return (<div className={`p-6 rounded-lg shadow-lg transition-all duration-300 ${darkMode ? 'bg-gray-800 text-white' : 'bg-gray-100'}`}><h2 className={`text-2xl font-bold mb-4 text-center pb-2 border-b-2 ${darkMode ? 'border-blue-400 text-blue-300' : 'border-blue-500 text-gray-800'}`}>Tailwind CSS 示例</h2><div className={`p-6 rounded-lg shadow-md transition-all duration-300 hover:shadow-lg hover:-translate-y-1 ${darkMode ? 'bg-gray-700' : 'bg-white'}`}><h3 className={`text-xl font-semibold text-center mb-4 ${darkMode ? 'text-white' : 'text-gray-800'}`}>计数器: <span className="font-bold">{count}</span></h3>{/* 条件渲染的消息框 */}{showMessage && (<div className={`p-4 mb-4 rounded border-l-4 ${getMessageClasses()} animate-fade-in`}><p className="font-medium">{messageType === 'success' && `计数器增加到 ${count}`}{messageType === 'warning' && `计数器减少到 ${count}`}{messageType === 'info' && `计数器重置为 ${count}`}</p></div>)}<div className="flex flex-wrap justify-center gap-3 mt-6"><button className="px-6 py-3 bg-blue-500 hover:bg-blue-600 text-white font-medium rounded-lg shadow transition-all duration-300 transform hover:scale-105 active:scale-95 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50"onClick={increment}>增加 (+1)</button><button className="px-6 py-3 bg-red-500 hover:bg-red-600 text-white font-medium rounded-lg shadow transition-all duration-300 transform hover:scale-105 active:scale-95 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-opacity-50"onClick={decrement}>减少 (-1)</button><button className="px-6 py-3 bg-green-500 hover:bg-green-600 text-white font-medium rounded-lg shadow transition-all duration-300 transform hover:scale-105 active:scale-95 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-opacity-50"onClick={reset}>重置</button></div></div>{/* 主题切换 */}<div className={`mt-6 p-6 rounded-lg shadow-md transition-all duration-300 ${darkMode ? 'bg-gray-700' : 'bg-white'}`}><h3 className={`text-xl font-semibold text-center mb-4 ${darkMode ? 'text-white' : 'text-gray-800'}`}>当前主题: <span className="font-bold">{darkMode ? '深色模式' : '浅色模式'}</span></h3><div className="flex justify-center"><button className={`px-6 py-3 font-medium rounded-lg shadow transition-all duration-300 transform hover:scale-105 active:scale-95 focus:outline-none ${darkMode ? 'bg-yellow-500 hover:bg-yellow-600 text-white' : 'bg-gray-800 hover:bg-gray-900 text-white'}`}onClick={toggleDarkMode}>切换到 {darkMode ? '浅色' : '深色'} 模式</button></div></div>{/* 动态样式示例 */}<div className={`mt-6 p-6 rounded-lg shadow-md transition-all duration-300 ${darkMode ? 'bg-gray-700' : 'bg-white'}`}><h3 className={`text-xl font-semibold text-center mb-4 ${darkMode ? 'text-white' : 'text-gray-800'}`}>动态样式示例</h3><div className={`p-4 rounded border-l-4 ${getDynamicClasses()}`}><p className="font-medium">{count > 0 ? '正数 - 成功样式' : count < 0 ? '负数 - 危险样式' : '零 - 信息样式'}</p></div></div>{/* 响应式设计示例 */}<div className={`mt-6 p-6 rounded-lg shadow-md transition-all duration-300 ${darkMode ? 'bg-gray-700' : 'bg-white'}`}><h3 className={`text-xl font-semibold text-center mb-4 ${darkMode ? 'text-white' : 'text-gray-800'}`}>响应式设计示例</h3><div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"><div className={`p-4 rounded-lg text-center transition-all duration-300 hover:shadow-lg ${darkMode ? 'bg-gray-600 hover:bg-gray-500' : 'bg-blue-50 hover:bg-blue-100'}`}><h4 className="font-bold">移动端</h4><p className="text-sm">单列布局</p></div><div className={`p-4 rounded-lg text-center transition-all duration-300 hover:shadow-lg ${darkMode ? 'bg-gray-600 hover:bg-gray-500' : 'bg-green-50 hover:bg-green-100'}`}><h4 className="font-bold">平板端</h4><p className="text-sm">双列布局</p></div><div className={`p-4 rounded-lg text-center transition-all duration-300 hover:shadow-lg ${darkMode ? 'bg-gray-600 hover:bg-gray-500' : 'bg-purple-50 hover:bg-purple-100'}`}><h4 className="font-bold">桌面端</h4><p className="text-sm">三列布局</p></div></div></div></div>);
}export default TailwindExample;

案例7:综合应用 - 完整的样式实践

import React, { useState, useEffect } from 'react';
import './ComprehensiveExample.css'; // 基础CSS
import styles from './ComprehensiveExample.module.css'; // CSS Modules// 行内样式对象
const inlineStyles = {heroSection: {padding: '60px 20px',textAlign: 'center',background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',color: 'white',borderRadius: '12px',margin: '20px 0',boxShadow: '0 10px 30px rgba(0,0,0,0.2)'},cardGrid: {display: 'grid',gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',gap: '20px',marginTop: '30px'}
};function ComprehensiveExample() {const [activeTab, setActiveTab] = useState('all');const [searchTerm, setSearchTerm] = useState('');const [darkMode, setDarkMode] = useState(false);const [animatedCards, setAnimatedCards] = useState([]);// 模拟数据const projects = [{ id: 1, title: '电商网站', category: 'web', status: 'completed', progress: 100 },{ id: 2, title: '移动应用', category: 'mobile', status: 'in-progress', progress: 65 },{ id: 3, title: '数据分析平台', category: 'web', status: 'planning', progress: 20 },{ id: 4, title: 'AI聊天机器人', category: 'ai', status: 'in-progress', progress: 80 },{ id: 5, title: '物联网系统', category: 'iot', status: 'completed', progress: 100 },{ id: 6, title: '区块链应用', category: 'blockchain', status: 'planning', progress: 10 }];// 过滤项目const filteredProjects = projects.filter(project => {const matchesTab = activeTab === 'all' || project.category === activeTab;const matchesSearch = project.title.toLowerCase().includes(searchTerm.toLowerCase());return matchesTab && matchesSearch;});// 切换暗色模式const toggleDarkMode = () => {setDarkMode(!darkMode);};// 动画效果useEffect(() => {const timer = setTimeout(() => {setAnimatedCards(filteredProjects.map(p => p.id));}, 300);return () => clearTimeout(timer);}, [filteredProjects]);// 获取状态相关的样式类const getStatusClass = (status) => {switch (status) {case 'completed': return styles.completed;case 'in-progress': return styles.inProgress;case 'planning': return styles.planning;default: return '';}};// 获取进度条样式const getProgressStyle = (progress) => ({width: `${progress}%`,height: '8px',borderRadius: '4px',backgroundColor: progress === 100 ? '#28a745' : '#007bff',transition: 'width 0.5s ease-in-out'});return (<div className={`${styles.container} ${darkMode ? styles.darkMode : ''}`}>{/* 英雄区域 - 行内样式 */}<div style={inlineStyles.heroSection}><h1 className={styles.heroTitle}>项目管理系统</h1><p className={styles.heroSubtitle}>管理您的所有项目,跟踪进度,提高效率</p><button className={styles.toggleButton}onClick={toggleDarkMode}aria-label={darkMode ? '切换到浅色模式' : '切换到深色模式'}>{darkMode ? '☀️ 浅色模式' : '🌙 深色模式'}</button></div>{/* 搜索和过滤 - CSS Modules */}<div className={styles.controls}><inputtype="text"placeholder="搜索项目..."value={searchTerm}onChange={(e) => setSearchTerm(e.target.value)}className={styles.searchInput}/><div className={styles.tabContainer}>{['all', 'web', 'mobile', 'ai', 'iot', 'blockchain'].map(tab => (<buttonkey={tab}className={`${styles.tabButton} ${activeTab === tab ? styles.activeTab : ''}`}onClick={() => setActiveTab(tab)}>{tab === 'all' ? '全部' : tab}</button>))}</div></div>{/* 项目卡片网格 - 行内样式 */}<div style={inlineStyles.cardGrid}>{filteredProjects.length === 0 ? (<div className={styles.noResults}><p>没有找到匹配的项目</p><button className={styles.resetButton}onClick={() => {setSearchTerm('');setActiveTab('all');}}>重置筛选条件</button></div>) : (filteredProjects.map(project => (<divkey={project.id}className={`${styles.card} ${animatedCards.includes(project.id) ? styles.animateIn : ''} ${getStatusClass(project.status)}`}><div className={styles.cardHeader}><h3 className={styles.cardTitle}>{project.title}</h3><span className={`${styles.statusBadge} ${styles[project.status]}`}>{project.status === 'completed' && '已完成'}{project.status === 'in-progress' && '进行中'}{project.status === 'planning' && '规划中'}</span></div><div className={styles.cardBody}><p className={styles.category}><strong>类别:</strong> {project.category}</p><div className={styles.progressContainer}><div className={styles.progressLabel}><span>进度</span><span>{project.progress}%</span></div><div className={styles.progressBarBackground}><div style={getProgressStyle(project.progress)}></div></div></div></div><div className={styles.cardFooter}><button className={styles.actionButton}>查看详情</button><button className={styles.secondaryButton}>编辑</button></div></div>)))}</div>{/* 统计信息 - CSS */}<div className="stats-container"><div className="stat-card"><h4>总项目数</h4><p className="stat-number">{projects.length}</p></div><div className="stat-card"><h4>已完成</h4><p className="stat-number">{projects.filter(p => p.status === 'completed').length}</p></div><div className="stat-card"><h4>进行中</h4><p className="stat-number">{projects.filter(p => p.status === 'in-progress').length}</p></div><div className="stat-card"><h4>平均进度</h4><p className="stat-number">{Math.round(projects.reduce((sum, p) => sum + p.progress, 0) / projects.length)}%</p></div></div></div>);
}export default ComprehensiveExample;

对应的 ComprehensiveExample.css

/* ComprehensiveExample.css */
.stats-container {display: grid;grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));gap: 20px;margin: 40px 0;
}.stat-card {background: white;padding: 20px;border-radius: 8px;text-align: center;box-shadow: 0 2px 10px rgba(0,0,0,0.05);transition: all 0.3s ease;
}.stat-card:hover {transform: translateY(-5px);box-shadow: 0 5px 20px rgba(0,0,0,0.1);
}.stat-card h4 {color: #666;font-size: 16px;margin-bottom: 10px;
}.stat-number {font-size: 32px;font-weight: bold;color: #333;
}/* 响应式设计 */
@media (max-width: 768px) {.stats-container {grid-template-columns: 1fr;}.stat-card {padding: 15px;}.stat-number {font-size: 24px;}
}

对应的 ComprehensiveExample.module.css

/* ComprehensiveExample.module.css */
.container {max-width: 1200px;margin: 0 auto;padding: 20px;font-family: 'Arial', sans-serif;
}.container.darkMode {background-color: #1a1a1a;color: #f0f0f0;
}.heroTitle {font-size: 2.5rem;margin: 0 0 15px 0;font-weight: 700;text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}.heroSubtitle {font-size: 1.2rem;margin: 0 0 30px 0;opacity: 0.9;
}.toggleButton {background: rgba(255,255,255,0.2);border: 2px solid rgba(255,255,255,0.3);color: white;padding: 12px 24px;border-radius: 30px;font-size: 16px;cursor: pointer;transition: all 0.3s ease;backdrop-filter: blur(10px);
}.toggleButton:hover {background: rgba(255,255,255,0.3);transform: translateY(-2px);
}.controls {display: flex;flex-wrap: wrap;gap: 20px;margin: 30px 0;padding: 20px;background: white;border-radius: 12px;box-shadow: 0 2px 15px rgba(0,0,0,0.05);
}.searchInput {flex: 1;min-width: 250px;padding: 12px 16px;border: 2px solid #e0e0e0;border-radius: 8px;font-size: 16px;transition: border-color 0.3s ease;
}.searchInput:focus {outline: none;border-color: #007bff;box-shadow: 0 0 0 3px rgba(0,38,155,0.1);
}.tabContainer {display: flex;flex-wrap: wrap;gap: 10px;
}.tabButton {padding: 8px 16px;background: #f0f0f0;border: none;border-radius: 20px;cursor: pointer;font-size: 14px;font-weight: 500;transition: all 0.3s ease;
}.tabButton:hover {background: #e0e0e0;
}.tabButton.activeTab {background: #007bff;color: white;
}.tabButton.activeTab:hover {background: #0056b3;
}.card {background: white;border-radius: 12px;overflow: hidden;box-shadow: 0 4px 20px rgba(0,0,0,0.08);transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);opacity: 0;transform: translateY(30px);
}.card.animateIn {opacity: 1;transform: translateY(0);
}.card:hover {transform: translateY(-10px) scale(1.02);box-shadow: 0 10px 30px rgba(0,0,0,0.15);
}.cardHeader {padding: 20px;border-bottom: 1px solid #eee;display: flex;justify-content: space-between;align-items: center;
}.cardTitle {margin: 0;font-size: 1.3rem;color: #333;font-weight: 600;
}.statusBadge {padding: 6px 12px;border-radius: 20px;font-size: 12px;font-weight: 600;text-transform: uppercase;letter-spacing: 0.5px;
}.completed {background: #d4edda;color: #155724;border-left: 4px solid #28a745;
}.inProgress {background: #cce5ff;color: #004085;border-left: 4px solid #007bff;
}.planning {background: #fff3cd;color: #856404;border-left: 4px solid #ffc107;
}.cardBody {padding: 20px;
}.category {color: #666;margin: 0 0 20px 0;font-size: 14px;
}.progressContainer {margin: 20px 0;
}.progressLabel {display: flex;justify-content: space-between;align-items: center;margin-bottom: 8px;font-size: 14px;color: #555;
}.progressBarBackground {width: 100%;height: 8px;background: #f0f0f0;border-radius: 4px;overflow: hidden;
}.cardFooter {padding: 20px;display: flex;gap: 10px;border-top: 1px solid #eee;
}.actionButton {flex: 1;padding: 10px;background: #007bff;color: white;border: none;border-radius: 6px;cursor: pointer;font-size: 14px;font-weight: 500;transition: all 0.3s ease;
}.actionButton:hover {background: #0056b3;transform: translateY(-2px);
}.secondaryButton {padding: 10px 15px;background: #f0f0f0;color: #555;border: none;border-radius: 6px;cursor: pointer;font-size: 14px;font-weight: 500;transition: all 0.3s ease;
}.secondaryButton:hover {background: #e0e0e0;transform: translateY(-2px);
}.noResults {grid-column: 1 / -1;text-align: center;padding: 60px 20px;background: #f8f9fa;border-radius: 12px;border: 2px dashed #dee2e6;
}.noResults p {font-size: 1.2rem;color: #666;margin: 0 0 20px 0;
}.resetButton {background: #007bff;color: white;border: none;padding: 12px 24px;border-radius: 6px;cursor: pointer;font-size: 16px;font-weight: 500;transition: all 0.3s ease;
}.resetButton:hover {background: #0056b3;transform: translateY(-2px);
}/* 暗色模式样式 */
.container.darkMode .controls {background: #2a2a2a;box-shadow: 0 2px 15px rgba(0,0,0,0.2);
}.container.darkMode .searchInput {background: #333;color: #fff;border-color: #444;
}.container.darkMode .searchInput:focus {border-color: #007bff;box-shadow: 0 0 0 3px rgba(0,123,255,0.2);
}.container.darkMode .tabButton {background: #333;color: #ccc;
}.container.darkMode .tabButton:hover {background: #444;
}.container.darkMode .tabButton.activeTab {background: #007bff;color: white;
}.container.darkMode .card {background: #2a2a2a;box-shadow: 0 4px 20px rgba(0,0,0,0.2);
}.container.darkMode .cardHeader {border-bottom-color: #444;
}.container.darkMode .cardTitle {color: #fff;
}.container.darkMode .category {color: #aaa;
}.container.darkMode .progressLabel {color: #ccc;
}.container.darkMode .progressBarBackground {background: #444;
}.container.darkMode .cardFooter {border-top-color: #444;
}.container.darkMode .secondaryButton {background: #333;color: #ccc;
}.container.darkMode .secondaryButton:hover {background: #444;
}/* 响应式设计 */
@media (max-width: 768px) {.container {padding: 15px;}.heroTitle {font-size: 2rem;}.controls {flex-direction: column;padding: 15px;}.searchInput {min-width: auto;}.tabContainer {justify-content: center;}.cardHeader {flex-direction: column;gap: 10px;text-align: center;}.cardFooter {flex-direction: column;}.actionButton, .secondaryButton {width: 100%;}
}

三、总结与最佳实践

1. 选择合适的样式方法

  • 小型项目/组件: 行内样式或CSS样式表
  • 中大型项目: CSS Modules或Styled-components
  • 团队协作: CSS Modules(避免命名冲突)
  • 设计系统: Styled-components(主题支持好)
  • 快速原型: Tailwind CSS

2. 最佳实践

  • 命名规范: 使用有意义的类名,遵循BEM或类似规范
  • 组件化: 每个组件有自己的样式,避免全局污染
  • 性能考虑: 避免过度使用行内样式,特别是大型列表
  • 可维护性: 将样式与逻辑分离,使用CSS变量或主题
  • 响应式设计: 始终考虑不同屏幕尺寸的适配

3. 常见问题解决

  • 样式不生效: 检查className拼写、CSS文件是否正确导入
  • 样式冲突: 使用CSS Modules或更具体的类名
  • 性能问题: 避免在render中创建样式对象,使用useMemo
  • 动态样式: 使用状态管理,避免直接操作DOM

4. 学习建议

  1. 从CSS样式表开始,熟悉基础
  2. 学习CSS Modules,理解局部作用域
  3. 尝试Styled-components,体验CSS-in-JS
  4. 掌握Tailwind CSS,提高开发效率
  5. 学习Sass/SCSS,增强CSS能力

通过以上全面的介绍和详细的案例代码,你应该能够掌握React中各种样式方法的使用。记住,选择适合自己项目和团队的样式方案最重要,不必追求最新最酷的技术,而要注重可维护性和团队协作效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/95828.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/95828.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/95828.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Proxychains 配置全解析:从入门到高级应用

引言 在数字时代&#xff0c;网络隐私与安全至关重要。无论是绕过地理限制访问内容&#xff0c;还是在渗透测试中隐藏踪迹&#xff0c;代理工具都不可或缺。Proxychains&#xff08;或称 Proxychains-NG&#xff09;作为一款经典的开源代理链工具&#xff0c;以其高效灵活的特性…

二叉树的前中后序遍历(迭代法)

目录 题目链接&#xff1a; 题目&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 前序遍历&#xff1a; 中序遍历&#xff1a; 后序遍历&#xff1a; 总结&#xff1a; 题目链接&#xff1a; 144. 二叉树的前序遍历 - 力扣&#xff08;LeetCode&#xff09; 94. …

redis的数据类型:string

文章目录String类型介绍redis采用的字符集json类型介绍String类型的命令set key value [EX seconds] [NX|XX]incr keyincr对操作的key对应的value类型有限制吗&#xff1f;incr key操作的返回值是什么&#xff1f;incr操作的key可以不存在吗&#xff1f;多个客户端同时针对同…

传统神经网络实现-----手写数字识别(MNIST)项目

完整代码&#xff1a;# import torch # print(torch.__version__)#1.X 1、验证安装的开发环境是否正确&#xff0c; MNIST包含70,000张手写数字图像: 60,000张用于训练&#xff0c;10,000张用于测试。 图像是灰度的&#xff0c;28x28像素的&#xff0c;并且居中的&#xff…

工业机器人标杆的数字化突围,珞石机器人如何以CRM实现业务重塑

在智能制造浪潮下&#xff0c;工业机器人行业正迎来快速增长。作为国内领先的机器人制造商&#xff0c;珞石机器人面对业务规模的迅速扩张&#xff0c;意识到传统的管理方式已无法满足企业发展需求&#xff0c;急需通过数字化升级破解管理难题。因此珞石机器人选择引入纷享销客…

NVIDIA GPU的指令集详细介绍

这是一个非常核心且深入的话题。GPU的指令集架构&#xff08;Instruction Set Architecture, ISA&#xff09;是理解GPU如何工作的关键&#xff0c;它直接体现了GPU为大规模并行计算而生的设计哲学。下面我将详细、全面地介绍GPU的指令集。 第一部分&#xff1a;核心哲学 —— …

Day 17: 3D点云深度学习专项 - 理论深度与面试精通之路

Day 17: 3D点云深度学习专项 - 理论深度与面试精通之路 🎯 学习目标:深度理解3D点云核心理论,获得该领域面试入场券 ⏰ 预计用时:6小时 (理论深度4h + 面试准备2h) 🎨 教学特色:理论优先 + 概念深度 + 面试导向 + 行业认知 🎯 今日学习大纲 1. 点云AI的理论基础:几何…

【经济学】量化模型TradingAgents 工具集成层与数据(财报+ 基本信息指标+基本面分析)+ChromaDB 客户端+财务情况记忆库

文章目录Toolkit 作用Toolkit 逐函数解析1. 获取默认配置2. update_config3. config4. __init__5. get_reddit_news6. get_finnhub_news7. get_reddit_stock_info8. get_chinese_social_sentiment9. get_finnhub_company_insider_sentiment10. get_YFin_data11. get_YFin_data_…

Uni-App + Vue onLoad与onLaunch执行顺序问题完整解决方案 – 3种实用方法详解

导读&#xff1a;在 Uni-app Vue 小程序应用开发中&#xff0c;你是否遇到过页面加载时全局数据还未准备好的问题&#xff1f;本文将深入分析onLoad生命周期钩子在onLaunch未完成时就执行的常见问题&#xff0c;并提供三种实用的解决方案。 &#x1f4cb; 问题描述 在 Vue 应…

25、SSH远程部署到另一台机器

25、SSH远程部署到另一台机器 因为不是每一台服务器都有jenkins的&#xff0c;一般都是一台jenkins&#xff0c;部署很多机器 1、安装插件 Publish Over SSH2、配置另一台机器 # 生成秘钥 ssh-keygen -t dsa# 把公钥复制到要访问的机器 ssh-copy-id root目标机器的ip# 第一次要…

2025年金融专业人士职业认证发展路径分析

在金融行业数字化转型的背景下&#xff0c;专业认证作为提升个人能力的一种方式&#xff0c;受到越来越多从业者的关注。本文基于行业发展趋势&#xff0c;分析6个金融相关领域的专业资格认证&#xff0c;为职业发展提供参考。一、CDA数据分析师认证含金量CDA数据分析师是数据领…

日用百货新零售小程序设计与开发(代码+数据库+LW)

摘要 本文设计并开发了一款基于Java、Spring Boot和MySQL的日用百货新零售小程序&#xff0c;旨在通过数字化手段优化日用百货的销售与配送流程&#xff0c;满足用户便捷购物的需求。系统采用前后端分离架构&#xff0c;前端通过微信小程序实现用户交互&#xff0c;后端基于Sp…

【Git】查看差异 删除文件 忽略文件

- 第 122 篇 - Date: 2025 - 09 - 07 Author: 郑龙浩&#xff08;仟墨&#xff09; 文章目录查看差异 && 删除文件 && 忽略文件1 git diff 可以查看哪些&#xff1f;基本用法比较不同提交比较分支文件比较其他2 彻底删除文件3 忽略文件「1」应该忽略哪些文件&a…

HarmonyOS应用开发:三层工程架构

引言 在HarmonyOS应用开发过程中&#xff0c;随着项目规模的增长&#xff0c;代码的组织结构显得尤为重要。 DevEco Studio创建出的默认工程仅包含一个entry类型的模块&#xff0c;如果直接使用平级目录进行模块管理&#xff0c;工程逻辑结构较混乱且模块间的一栏关系不够清晰&…

phpMyAdmin文件包含漏洞复现:原理详解+环境搭建+渗透实战(windows CVE-2018-12613)

目录 一、CVE-2018-12613漏洞 1、漏洞简介 2、漏洞原理 &#xff08;1&#xff09;漏洞触发点与正常逻辑 &#xff08;2&#xff09;过滤逻辑缺陷与绕过方式 二、渗透准备 1、访问phpmyadmin靶场 2、登录phpmyadmin 3、获取session文件位置 三、渗透准备 1、读取敏感…

Jakarta EE(基于 JPA)在 IntelliJ IDEA 中开发简单留言板应用的实验指导

Jakarta EE&#xff08;基于 JPA&#xff09;在 IntelliJ IDEA 中开发简单留言板应用的实验指导摘要&#xff1a;Jakarta EE 并不仅限于使用 H2 数据库&#xff0c;它支持任何符合 JDBC 或 JPA 标准的数据库&#xff0c;例如 MySQL、PostgreSQL、Oracle 等。H2 通常用于开发测试…

Gitea:轻量级的自托管Git服务

欢迎光临我的个人博客查看最新文章&#xff1a;rivers blog 在当今的软件开发世界中&#xff0c;代码托管平台是必不可少的工具。而对于寻求自主控制和数据隐私的团队与开发者来说&#xff0c;Gitea提供了一个完美的解决方案。 1、 Gitea简介 Gitea&#xff08;发音为ɡɪˈti…

深度学习-----简单入门卷积神经网络CNN的全流程

&#xff08;一&#xff09;卷积神经网络&#xff08;CNN&#xff09;的核心思想传统全连接网络的缺陷图像平铺展开后&#xff0c;旋转或位置变化会导致输入差异大&#xff0c;难以识别举例&#xff1a;手写数字“8”在不同位置或旋转后的识别困难&#xff08;图像在计算机中是…

Scikit-learn Python机器学习 - 特征降维 压缩数据 - 特征选择 - 单变量特征选择 SelectKBest - 选择Top K个特征

锋哥原创的Scikit-learn Python机器学习视频教程&#xff1a; 2026版 Scikit-learn Python机器学习 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 课程介绍 本课程主要讲解基于Scikit-learn的Python机器学习知识&#xff0c;包括机器学习概述&#xff0c;特征工程(数据…

Datawhale AI夏令营复盘[特殊字符]:我如何用一个Prompt,在Coze Space上“画”出一个商业级网页?

文章摘要 本文详细记录了我在Datawhale AI夏令营期间&#xff0c;如何另辟蹊径&#xff0c;使用Coze&#xff08;扣子空间&#xff09;和精心设计的Prompt&#xff0c;从零开始构建一个专业的“智能SEO Agent”产品网页的完整过程。文章将完整展示我编写的“万字”级Prompt&…