雅地處理?xiàng)l件渲染)
React 中如何優(yōu)雅地處理?xiàng)l件渲染一句話總結(jié)三元表達(dá)式適合「二選一」 適合「顯示/隱藏」立即執(zhí)行函數(shù) IIFE 復(fù)雜邏輯兜底抽出子組件才是終極方案。別在 JSX 里寫 if-else用對(duì)了方式條件渲染既干凈又不容易出 bug正文目錄條件渲染有哪些方式5 大高頻場(chǎng)景 代碼示例萬(wàn)能兜底條件渲染決策表預(yù)防 checklist不再踩坑一句話總結(jié)一、條件渲染有哪些方式問(wèn)題背景JSX 本質(zhì)是 JavaScript不能直接寫if-elseReact 提供了多種條件渲染方式但用錯(cuò)了會(huì)導(dǎo)致渲染異常、性能浪費(fèi)或代碼可讀性差。方式適用場(chǎng)景特點(diǎn)三元表達(dá)式? :二選一簡(jiǎn)潔返回值邏輯與顯示/隱藏短路求值IIFE 立即執(zhí)行函數(shù)復(fù)雜邏輯可寫 if-else但可讀性差抽取子組件復(fù)用/復(fù)雜條件最推薦可維護(hù)switch IIFE多條件分支比 if-else 清晰enum對(duì)象映射狀態(tài)映射渲染最優(yōu)雅的多分支// ? 錯(cuò)誤JSX 中不能直接寫 if-else function App({ status }) { return ( div if (status loading) { // 這會(huì)被當(dāng)字符串渲染 Loading / } /div ) }二、5 大高頻場(chǎng)景 代碼示例場(chǎng)景 1加載狀態(tài) → 用 最常見(jiàn)場(chǎng)景數(shù)據(jù)沒(méi)加載完顯示 Loading加載完顯示內(nèi)容。// ? 正確 適合「滿足條件才顯示」 function UserList({ users, loading }) { return ( div {loading Spinner /} {!loading users.map(u div key{u.id}{u.name}/div)} /div ) }// ? 錯(cuò)誤 與數(shù)字 0 的坑 function App({ count }) { return ( div {count Badge text{count} /} /div ) } // count 為 0 時(shí)渲染出 0 而不是什么都不顯示// ? 正確避免 0 的坑 function App({ count }) { return ( div {count 0 Badge text{count} /} {/* 或 */} {!!count Badge text{count} /} /div ) }場(chǎng)景 2二選一 → 用三元表達(dá)式登錄/未登錄、有數(shù)據(jù)/空狀態(tài)用三元最清晰。// ? 正確三元表達(dá)式二選一 function Greeting({ user }) { return ( div {user ? Welcome name{user.name} / : LoginButton /} /div ) }// ? 不推薦 疊 實(shí)現(xiàn)二選一 function Greeting({ user }) { return ( div {user Welcome name{user.name} /} {!user LoginButton /} /div ) } // 能用但啰嗦且兩個(gè)條件都執(zhí)行場(chǎng)景 3多狀態(tài)切換 → 用對(duì)象映射loading / success / error 三種狀態(tài)用對(duì)象映射比 if-else 優(yōu)雅得多。// ? 正確對(duì)象映射清晰優(yōu)雅 function StatusView({ status, data, error }) { const statusMap { loading: Spinner /, success: DataList data{data} /, error: ErrorMessage error{error} /, empty: EmptyState / } return div{statusMap[status] ?? DefaultView /}/div }// ? 糟糕嵌套三元表達(dá)式難以閱讀 function StatusView({ status, data, error }) { return ( div {status loading ? Spinner / : status success ? DataList data{data} / : status error ? ErrorMessage error{error} / : EmptyState /} /div ) }場(chǎng)景 4復(fù)雜條件邏輯 → 抽子組件條件里有循環(huán)、有副作用、有復(fù)雜判斷抽成子組件最清晰。// ? 正確復(fù)雜邏輯抽子組件 function ProductList({ products, filter, sort }) { return ( div ProductGrid products{products} filter{filter} sort{sort} / /div ) } function ProductGrid({ products, filter, sort }) { const visible products .filter(filter) .sort(sort) if (visible.length 0) { return EmptyState message沒(méi)有符合條件的商品 / } return ( ul {visible.map(p ( li key{p.id}{p.name} - ¥{p.price}/li ))} /ul ) }// ? 糟糕在 JSX 里塞一堆邏輯 function ProductList({ products, filter, sort }) { return ( div {(() { const visible products.filter(filter).sort(sort) if (visible.length 0) { return EmptyState message沒(méi)有符合條件的商品 / } return ( ul {visible.map(p ( li key{p.id}{p.name} - ¥{p.price}/li ))} /ul ) })()} /div ) } // IIFE 能用但可讀性差lint 也不推薦場(chǎng)景 5條件 className → 用工具函數(shù)條件渲染不只是組件className 的條件拼接也是高頻場(chǎng)景。// ? 正確用 clsx / classnames 工具 import clsx from clsx function Button({ variant, size, disabled, children }) { return ( button className{clsx( btn, btn-${variant}, // btn-primary / btn-secondary btn-${size}, // btn-sm / btn-lg { btn-disabled: disabled, // 條件為 true 時(shí)添加 btn-active: !disabled } )} {children} /button ) }// ? 糟糕手動(dòng)拼接字符串 function Button({ variant, size, disabled }) { let className btn btn- variant btn- size if (disabled) { className btn-disabled } else { className btn-active } return button className{className}Click/button }三、萬(wàn)能兜底條件渲染決策表場(chǎng)景推薦方式示例滿足條件才顯示{loading Spinner /}二選一三元表達(dá)式{user ? A / : B /}三選一及以上對(duì)象映射statusMap[status]復(fù)雜邏輯判斷抽子組件ProductGrid ... /條件 classNameclsx工具clsx(btn, { active })數(shù)字 0 的坑 0 或!!{count 0 Badge /}組件 show/hide 頻繁切換CSSdisplaydiv style{{ display: show ? : none }}萬(wàn)能決策流程條件有幾個(gè)分支 → 1 個(gè)滿足才顯示→ 用 → 2 個(gè) → 用三元表達(dá)式 → 3 個(gè)及以上 → 用對(duì)象映射 → 邏輯太復(fù)雜 → 抽子組件// 萬(wàn)能模板 function View({ status, data, error }) { // 復(fù)雜邏輯先抽出來(lái) if (status loading) return Spinner / if (status error) return ErrorMessage error{error} / if (!data || data.length 0) return EmptyState / // 簡(jiǎn)單條件用 return ( div {data.length 10 Pagination total{data.length} /} DataList data{data} / /div ) }四、預(yù)防 checklist不再踩坑左側(cè)是數(shù)字時(shí)用 0或!!避免0被渲染不要在 JSX 中寫if-else用三元或 IIFE嵌套三元超過(guò) 2 層 → 換對(duì)象映射或抽子組件IIFE 只在萬(wàn)不得已時(shí)用優(yōu)先抽子組件組件內(nèi)提前return處理 loading/error 狀態(tài)減少嵌套條件 className 用clsx/classnames不要手動(dòng)拼字符串頻繁切換的組件用 CSSdisplay而非卸載/掛載保留狀態(tài)switch語(yǔ)句放在組件外部或 IIFE 中不要直接寫在 JSX五、一句話總結(jié)一個(gè)分支用 兩個(gè)分支用三元三個(gè)以上用對(duì)象映射邏輯復(fù)雜就抽子組件——條件渲染的本質(zhì)就是把 if-else 翻譯成 JSX 能接受的形式。最后問(wèn)候親愛(ài)的朋友們并邀請(qǐng)你們閱讀我的全新著作 《React進(jìn)階之路》