React學習教程,從入門到精通, React 樣式語法知識點與案例詳解(13)

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&…