React 条件判断
概述
条件渲染是 React 中最常用的功能之一,它让我们能够根据不同的条件显示不同的内容。本章将深入学习各种条件判断的方法、最佳实践以及性能优化技巧。
🔀 基础条件判断
if 语句
jsx
function ConditionalWithIf() {
const [user, setUser] = React.useState(null);
const [loading, setLoading] = React.useState(false);
const login = () => {
setLoading(true);
setTimeout(() => {
setUser({ name: '张三', role: 'admin' });
setLoading(false);
}, 1000);
};
const logout = () => {
setUser(null);
};
// 使用 if 语句进行条件判断
if (loading) {
return (
<div style={{ textAlign: 'center', padding: '50px' }}>
<div>⏳ 登录中...</div>
</div>
);
}
if (user) {
return (
<div>
<h2>欢迎,{user.name}!</h2>
<p>您的角色:{user.role}</p>
<button onClick={logout}>登出</button>
</div>
);
}
return (
<div>
<h2>请登录</h2>
<button onClick={login}>登录</button>
</div>
);
}三元运算符
jsx
function ConditionalWithTernary() {
const [theme, setTheme] = React.useState('light');
const [notifications, setNotifications] = React.useState([]);
const [showSettings, setShowSettings] = React.useState(false);
const addNotification = () => {
const newNotification = {
id: Date.now(),
message: `通知 ${notifications.length + 1}`,
type: Math.random() > 0.5 ? 'info' : 'warning'
};
setNotifications([...notifications, newNotification]);
};
const toggleTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light');
};
const themeStyles = {
light: { backgroundColor: '#fff', color: '#000' },
dark: { backgroundColor: '#333', color: '#fff' }
};
return (
<div style={{ ...themeStyles[theme], padding: '20px', minHeight: '400px' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<h2>条件渲染演示</h2>
{/* 简单三元运算符 */}
<button onClick={toggleTheme}>
{theme === 'light' ? '🌙 深色模式' : '☀️ 浅色模式'}
</button>
</div>
<div style={{ marginBottom: '20px' }}>
<button onClick={addNotification} style={{ marginRight: '10px' }}>
添加通知
</button>
<button onClick={() => setShowSettings(!showSettings)}>
{showSettings ? '隐藏设置' : '显示设置'}
</button>
</div>
{/* 嵌套三元运算符 */}
<div>
{notifications.length === 0 ? (
<p>暂无通知</p>
) : notifications.length === 1 ? (
<p>您有 1 条新通知</p>
) : (
<p>您有 {notifications.length} 条新通知</p>
)}
</div>
{/* 条件显示设置面板 */}
{showSettings ? (
<div style={{
border: '1px solid #ddd',
padding: '15px',
marginTop: '20px',
borderRadius: '5px'
}}>
<h3>设置面板</h3>
<label>
<input
type="checkbox"
checked={theme === 'dark'}
onChange={toggleTheme}
/>
深色模式
</label>
</div>
) : null}
{/* 通知列表 */}
<div style={{ marginTop: '20px' }}>
{notifications.map(notification => (
<div
key={notification.id}
style={{
padding: '10px',
margin: '5px 0',
backgroundColor: notification.type === 'warning' ? '#fff3cd' : '#d1ecf1',
color: notification.type === 'warning' ? '#856404' : '#0c5460',
borderRadius: '4px'
}}
>
{notification.type === 'warning' ? '⚠️' : 'ℹ️'} {notification.message}
</div>
))}
</div>
</div>
);
}逻辑与运算符
jsx
function ConditionalWithLogicalAnd() {
const [user, setUser] = React.useState({
name: '张三',
isVip: true,
credits: 150,
hasNotifications: true,
unreadCount: 5
});
const [showModal, setShowModal] = React.useState(false);
const [errors, setErrors] = React.useState([]);
const addError = () => {
setErrors([...errors, `错误 ${errors.length + 1}: 这是一个示例错误`]);
};
const clearErrors = () => {
setErrors([]);
};
return (
<div style={{ padding: '20px' }}>
<h2>逻辑与运算符演示</h2>
{/* 基础条件显示 */}
{user && (
<div style={{ marginBottom: '20px' }}>
<h3>用户信息</h3>
<p>姓名: {user.name}</p>
{/* VIP 徽章 */}
{user.isVip && (
<span style={{
backgroundColor: '#ffd700',
color: '#000',
padding: '2px 8px',
borderRadius: '10px',
fontSize: '12px'
}}>
👑 VIP
</span>
)}
{/* 积分显示 */}
{user.credits > 100 && (
<div style={{ color: 'green', marginTop: '10px' }}>
🎉 恭喜!您的积分已超过 100 分!
</div>
)}
{/* 通知提醒 */}
{user.hasNotifications && user.unreadCount > 0 && (
<div style={{
backgroundColor: '#ff4757',
color: 'white',
padding: '10px',
borderRadius: '5px',
marginTop: '10px'
}}>
📬 您有 {user.unreadCount} 条未读通知
</div>
)}
</div>
)}
{/* 错误显示 */}
{errors.length > 0 && (
<div style={{ marginBottom: '20px' }}>
<h3>错误列表</h3>
{errors.map((error, index) => (
<div key={index} style={{
backgroundColor: '#f8d7da',
color: '#721c24',
padding: '10px',
margin: '5px 0',
borderRadius: '4px',
border: '1px solid #f5c6cb'
}}>
❌ {error}
</div>
))}
<button onClick={clearErrors} style={{
backgroundColor: '#dc3545',
color: 'white',
border: 'none',
padding: '8px 16px',
borderRadius: '4px'
}}>
清除所有错误
</button>
</div>
)}
<div>
<button onClick={addError} style={{ marginRight: '10px' }}>
添加错误
</button>
<button onClick={() => setShowModal(true)}>
显示模态框
</button>
</div>
{/* 模态框 */}
{showModal && (
<div style={{
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0,0,0,0.5)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
zIndex: 1000
}}>
<div style={{
backgroundColor: 'white',
padding: '30px',
borderRadius: '8px',
maxWidth: '400px',
width: '90%'
}}>
<h3>模态框标题</h3>
<p>这是一个条件显示的模态框。</p>
<button
onClick={() => setShowModal(false)}
style={{
backgroundColor: '#007bff',
color: 'white',
border: 'none',
padding: '10px 20px',
borderRadius: '4px'
}}
>
关闭
</button>
</div>
</div>
)}
</div>
);
}🎯 复杂条件判断
Switch 语句模拟
jsx
function ComplexConditionals() {
const [status, setStatus] = React.useState('idle');
const [userRole, setUserRole] = React.useState('guest');
const [errorType, setErrorType] = React.useState(null);
// 状态渲染函数
const renderStatus = () => {
switch (status) {
case 'loading':
return (
<div style={{ textAlign: 'center', color: '#007bff' }}>
⏳ 正在加载...
</div>
);
case 'success':
return (
<div style={{ textAlign: 'center', color: '#28a745' }}>
✅ 操作成功完成
</div>
);
case 'error':
return (
<div style={{ textAlign: 'center', color: '#dc3545' }}>
❌ 操作失败,请重试
</div>
);
case 'idle':
default:
return (
<div style={{ textAlign: 'center', color: '#6c757d' }}>
💤 等待操作
</div>
);
}
};
// 用户界面渲染
const renderUserInterface = () => {
const interfaces = {
admin: (
<div style={{ backgroundColor: '#e7f3ff', padding: '20px', borderRadius: '8px' }}>
<h3>👑 管理员控制台</h3>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '10px' }}>
<button>用户管理</button>
<button>系统设置</button>
<button>数据统计</button>
<button>安全中心</button>
</div>
</div>
),
moderator: (
<div style={{ backgroundColor: '#fff3e0', padding: '20px', borderRadius: '8px' }}>
<h3>🛡️ 版主面板</h3>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '10px' }}>
<button>内容审核</button>
<button>用户举报</button>
<button>社区管理</button>
<button>数据报告</button>
</div>
</div>
),
vip: (
<div style={{ backgroundColor: '#f3e5f5', padding: '20px', borderRadius: '8px' }}>
<h3>💎 VIP 专区</h3>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '10px' }}>
<button>专属服务</button>
<button>高级功能</button>
<button>优先支持</button>
<button>特权礼品</button>
</div>
</div>
),
user: (
<div style={{ backgroundColor: '#e8f5e8', padding: '20px', borderRadius: '8px' }}>
<h3>👤 用户中心</h3>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '10px' }}>
<button>个人资料</button>
<button>订单管理</button>
<button>收藏夹</button>
<button>设置</button>
</div>
</div>
),
guest: (
<div style={{ backgroundColor: '#f8f9fa', padding: '20px', borderRadius: '8px' }}>
<h3>🚪 访客模式</h3>
<p>请登录以获取完整功能</p>
<div style={{ display: 'flex', gap: '10px' }}>
<button style={{ backgroundColor: '#007bff', color: 'white', border: 'none', padding: '10px 20px', borderRadius: '4px' }}>
登录
</button>
<button style={{ backgroundColor: '#28a745', color: 'white', border: 'none', padding: '10px 20px', borderRadius: '4px' }}>
注册
</button>
</div>
</div>
)
};
return interfaces[userRole] || interfaces.guest;
};
// 错误类型处理
const renderError = () => {
if (!errorType) return null;
const errorMessages = {
network: {
icon: '🌐',
title: '网络错误',
message: '请检查您的网络连接',
color: '#ff6b6b'
},
auth: {
icon: '🔐',
title: '认证失败',
message: '请重新登录',
color: '#ffa502'
},
permission: {
icon: '🚫',
title: '权限不足',
message: '您没有执行此操作的权限',
color: '#ff4757'
},
server: {
icon: '🔧',
title: '服务器错误',
message: '服务器暂时不可用,请稍后重试',
color: '#5f27cd'
}
};
const error = errorMessages[errorType];
return (
<div style={{
backgroundColor: error.color + '20',
border: `1px solid ${error.color}`,
borderRadius: '8px',
padding: '15px',
margin: '20px 0'
}}>
<div style={{ display: 'flex', alignItems: 'center', marginBottom: '10px' }}>
<span style={{ fontSize: '24px', marginRight: '10px' }}>{error.icon}</span>
<h4 style={{ margin: 0, color: error.color }}>{error.title}</h4>
</div>
<p style={{ margin: 0, color: '#333' }}>{error.message}</p>
<button
onClick={() => setErrorType(null)}
style={{
marginTop: '10px',
backgroundColor: error.color,
color: 'white',
border: 'none',
padding: '8px 16px',
borderRadius: '4px'
}}
>
关闭
</button>
</div>
);
};
return (
<div style={{ padding: '20px', maxWidth: '800px', margin: '0 auto' }}>
<h2>复杂条件判断演示</h2>
{/* 状态控制 */}
<div style={{ marginBottom: '20px' }}>
<h3>状态控制</h3>
<div style={{ display: 'flex', gap: '10px', marginBottom: '15px' }}>
{['idle', 'loading', 'success', 'error'].map(s => (
<button
key={s}
onClick={() => setStatus(s)}
style={{
backgroundColor: status === s ? '#007bff' : '#f8f9fa',
color: status === s ? 'white' : '#333',
border: '1px solid #ddd',
padding: '8px 16px',
borderRadius: '4px'
}}
>
{s}
</button>
))}
</div>
{renderStatus()}
</div>
{/* 用户角色切换 */}
<div style={{ marginBottom: '20px' }}>
<h3>用户角色</h3>
<select
value={userRole}
onChange={(e) => setUserRole(e.target.value)}
style={{ padding: '8px', marginBottom: '15px' }}
>
<option value="guest">访客</option>
<option value="user">普通用户</option>
<option value="vip">VIP用户</option>
<option value="moderator">版主</option>
<option value="admin">管理员</option>
</select>
{renderUserInterface()}
</div>
{/* 错误类型演示 */}
<div>
<h3>错误处理</h3>
<div style={{ display: 'flex', gap: '10px', marginBottom: '15px' }}>
{['network', 'auth', 'permission', 'server'].map(type => (
<button
key={type}
onClick={() => setErrorType(type)}
style={{
backgroundColor: '#dc3545',
color: 'white',
border: 'none',
padding: '8px 16px',
borderRadius: '4px'
}}
>
{type} 错误
</button>
))}
</div>
{renderError()}
</div>
</div>
);
}多重条件组合
jsx
function MultipleConditions() {
const [user, setUser] = React.useState({
isLoggedIn: false,
isVip: false,
credits: 0,
level: 1
});
const [appState, setAppState] = React.useState({
isOnline: true,
maintenance: false,
feature: {
chatEnabled: true,
paymentEnabled: true,
analyticsEnabled: false
}
});
const toggleLogin = () => {
setUser(prev => ({
...prev,
isLoggedIn: !prev.isLoggedIn,
credits: prev.isLoggedIn ? 0 : 150,
level: prev.isLoggedIn ? 1 : 3
}));
};
const toggleVip = () => {
setUser(prev => ({ ...prev, isVip: !prev.isVip }));
};
const toggleMaintenance = () => {
setAppState(prev => ({ ...prev, maintenance: !prev.maintenance }));
};
const canAccessFeature = (feature) => {
return user.isLoggedIn &&
appState.isOnline &&
!appState.maintenance &&
appState.feature[feature];
};
const canAccessVipFeature = () => {
return user.isLoggedIn &&
user.isVip &&
user.level >= 3 &&
appState.isOnline;
};
const showPaymentOptions = () => {
return user.isLoggedIn &&
user.credits < 100 &&
canAccessFeature('paymentEnabled');
};
return (
<div style={{ padding: '20px' }}>
<h2>多重条件判断</h2>
{/* 控制面板 */}
<div style={{
backgroundColor: '#f8f9fa',
padding: '15px',
borderRadius: '8px',
marginBottom: '20px'
}}>
<h3>控制面板</h3>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '10px' }}>
<button onClick={toggleLogin}>
{user.isLoggedIn ? '登出' : '登录'}
</button>
<button onClick={toggleVip} disabled={!user.isLoggedIn}>
{user.isVip ? '取消VIP' : '开通VIP'}
</button>
<button onClick={toggleMaintenance}>
{appState.maintenance ? '结束维护' : '开始维护'}
</button>
</div>
<div style={{ marginTop: '10px', fontSize: '14px' }}>
<span>在线: {appState.isOnline ? '✅' : '❌'}</span>
<span style={{ marginLeft: '20px' }}>
维护模式: {appState.maintenance ? '🔧' : '✅'}
</span>
</div>
</div>
{/* 用户状态显示 */}
<div style={{ marginBottom: '20px' }}>
{user.isLoggedIn ? (
<div style={{
backgroundColor: '#d4edda',
padding: '15px',
borderRadius: '8px',
border: '1px solid #c3e6cb'
}}>
<h3>用户信息</h3>
<p>状态: 已登录 {user.isVip && '👑 VIP'}</p>
<p>积分: {user.credits}</p>
<p>等级: {user.level}</p>
</div>
) : (
<div style={{
backgroundColor: '#f8d7da',
padding: '15px',
borderRadius: '8px',
border: '1px solid #f5c6cb'
}}>
<h3>未登录</h3>
<p>请登录以使用全部功能</p>
</div>
)}
</div>
{/* 维护模式提示 */}
{appState.maintenance && (
<div style={{
backgroundColor: '#fff3cd',
border: '1px solid #ffeaa7',
padding: '15px',
borderRadius: '8px',
marginBottom: '20px'
}}>
🔧 系统正在维护中,部分功能可能不可用
</div>
)}
{/* 功能区域 */}
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
gap: '15px'
}}>
{/* 聊天功能 */}
<div style={{
border: '1px solid #ddd',
borderRadius: '8px',
padding: '15px',
opacity: canAccessFeature('chatEnabled') ? 1 : 0.5
}}>
<h4>💬 聊天功能</h4>
{canAccessFeature('chatEnabled') ? (
<div>
<p>聊天功能可用</p>
<button>开始聊天</button>
</div>
) : (
<div>
<p style={{ color: '#666' }}>
{!user.isLoggedIn && '请先登录'}
{user.isLoggedIn && appState.maintenance && '维护中暂时不可用'}
{user.isLoggedIn && !appState.feature.chatEnabled && '功能已禁用'}
</p>
</div>
)}
</div>
{/* VIP功能 */}
<div style={{
border: '1px solid #ddd',
borderRadius: '8px',
padding: '15px',
opacity: canAccessVipFeature() ? 1 : 0.5
}}>
<h4>👑 VIP专属功能</h4>
{canAccessVipFeature() ? (
<div>
<p>VIP功能可用</p>
<button>访问VIP区域</button>
</div>
) : (
<div>
<p style={{ color: '#666' }}>
{!user.isLoggedIn && '请先登录'}
{user.isLoggedIn && !user.isVip && '需要VIP会员'}
{user.isLoggedIn && user.isVip && user.level < 3 && '等级不足'}
{user.isLoggedIn && user.isVip && !appState.isOnline && '网络不可用'}
</p>
</div>
)}
</div>
{/* 支付选项 */}
<div style={{
border: '1px solid #ddd',
borderRadius: '8px',
padding: '15px',
opacity: showPaymentOptions() ? 1 : 0.5
}}>
<h4>💳 充值中心</h4>
{showPaymentOptions() ? (
<div>
<p>积分不足,需要充值</p>
<button>立即充值</button>
</div>
) : user.isLoggedIn && user.credits >= 100 ? (
<div>
<p style={{ color: 'green' }}>积分充足</p>
</div>
) : (
<div>
<p style={{ color: '#666' }}>
{!user.isLoggedIn && '请先登录'}
{user.isLoggedIn && !canAccessFeature('paymentEnabled') && '支付功能不可用'}
</p>
</div>
)}
</div>
</div>
{/* 条件组合示例 */}
<div style={{ marginTop: '30px' }}>
<h3>条件组合示例</h3>
<div style={{ fontSize: '14px', backgroundColor: '#f8f9fa', padding: '15px', borderRadius: '8px' }}>
<p><strong>聊天功能条件:</strong> 已登录 && 在线 && 非维护模式 && 功能开启</p>
<p><strong>VIP功能条件:</strong> 已登录 && VIP会员 && 等级≥3 && 在线</p>
<p><strong>充值提示条件:</strong> 已登录 && 积分<100 && 支付功能开启</p>
</div>
</div>
</div>
);
}📝 本章小结
通过本章学习,你应该掌握了:
条件判断方法
- ✅ if 语句:适用于复杂逻辑
- ✅ 三元运算符:简洁的二元判断
- ✅ 逻辑与运算符:简单的存在性检查
- ✅ Switch 模拟:多分支条件处理
最佳实践
- 选择合适的方法:根据复杂度选择判断方式
- 避免深层嵌套:使用早期返回和提取函数
- 条件组合:合理组织多重条件逻辑
- 性能优化:避免不必要的条件计算
- 可读性优先:保持代码清晰易懂
继续学习:下一章 - React 自定义 Hook