藉助React,我們可以構建動態且高度交互的單頁應用程式,充分利用這種交互性的一種方法是通過條件渲染。 ...
原文地址:https://scotch.io/tutorials/7-ways-to-implement-conditional-rendering-in-react-applications
藉助React,我們可以構建動態且高度交互的單頁應用程式,充分利用這種交互性的一種方法是通過條件渲染。
目錄
條件渲染一詞描述了根據某些條件渲染不同UI標簽的能力。在React文檔中,這是一種根據條件渲染不同元素或組件的方法。此概念通常被應用到如下情況中:
- 從API渲染外部數據
- 顯示/隱藏元素
- 切換應用程式功能
- 實現許可權級別
- 認證與授權
在本文中,我們將研究在React應用程式中實現條件渲染的7種方法。
挑戰
首先,根據在組件state中isLoggedIn
的值,我們希望能夠在用戶未登入時顯示Login
按鈕,在用戶登入時顯示Logout
按鈕。
下圖是我們初始組件的截圖:
代碼如下:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
isLoggedIn: true
};
}
render() {
return (
<div className="App">
<h1>
This is a Demo showing several ways to implement Conditional Rendering in React.
</h1>
<button>Login</button>
<button>Logout</button>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
線上測試:CodeSandBox
解決方法
在代碼段中,…表示某些與所解釋要點沒有直接聯繫的代碼。
1. 使用if…else語句
使用if…else
語句允許我們可以指出,如果條件為true
,則執行特定的操作,否則將執行其他操作。使用示例,我將測試if…else
通常用於在React中條件渲染的兩種方法。
- 將條件渲染提取到函數中
在JSX中,我們可以將JS代碼和HTML標簽放在一起,以確保程式內具有驚人的交互性。為此,我們使用大括弧{}
併在其中編寫我們的JS。但在括弧內能做事情也是有限的。例如,下麵代碼的結果並不能實現我們想要的結果。
// index.js
...
render() {
let {isLoggedIn} = this.state;
return (
<div className="App">
<h1>
This is a Demo showing several ways to implement Conditional Rendering in React.
</h1>
{
if(isLoggedIn){
return <button>Logout</button>
} else{
return <button>Login</button>
}
}
</div>
);
}
...
要瞭解更多相關信息,請訪問此鏈接。
為瞭解決這個問題,我們將條件邏輯提取到一個函數中,如下所示:
// index.js
...
render() {
let {isLoggedIn} = this.state;
const renderAuthButton = ()=>{
if(isLoggedIn){
return <button>Logout</button>
} else{
return <button>Login</button>
}
}
return (
<div className="App">
<h1>
This is a Demo showing several ways to implement Conditional Rendering
in React.
</h1>
{renderAuthButton()}
</div>
);
}
...
註意,我們將邏輯從JSX提取到函數renderAuthButton
中。因此,我們只需要在JSX大括弧內執行函數即可。
- 多個返回語句
在使用此方法時,組件必須儘可能的簡單,以避免兄弟或父組件的重新渲染。因此,我們創建了一個名為AuthButton
的新組件。
// AuthButton.js
import React from "react";
const AuthButton = props => {
let { isLoggedIn } = props;
if (isLoggedIn) {
return <button>Logout</button>;
} else {
return <button>Login</button>;
}
};
export default AuthButton;
AuthButton
根據通過組件屬性isLoggedIn
傳入的狀態值,返回不同的元素和組件。因此,我們將其導入index.js
並將狀態值傳入,如下所示:
// index.js
...
import AuthButton from "./AuthButton";
...
render() {
let { isLoggedIn } = this.state;
return (
<div className="App">
...
<AuthButton isLoggedIn={isLoggedIn} />
</div>
);
}
...
一定要避免下麵的操作:
// index.js
...
render() {
let { isLoggedIn } = this.state;
if (isLoggedIn) {
return (
<div className="App">
<h1>
This is a Demo showing several ways to implement Conditional
Rendering in React.
</h1>
<button>Logout</button>;
</div>
);
} else {
return (
<div className="App">
<h1>
This is a Demo showing several ways to implement Conditional
Rendering in React.
</h1>
<button>Login</button>
</div>
);
}
}
...
雖然上述代碼將實現相同的結果,但使得組件不必要的臃腫,同時由於不斷重新渲染一個不變的組件而導致性能問題。
2. 使用元素變數
元素變數是上述的將條件渲染提取到函數中的一個擴展。元素變數只是保存JSX元素的變數。因此,我們可以在JSX外部根據條件將元素/組件賦值給這些變數,僅在JSX渲染變數即可。
// index.js
...
render() {
let { isLoggedIn } = this.state;
let AuthButton;
if (isLoggedIn) {
AuthButton = <button>Logout</button>;
} else {
AuthButton = <button>Login</button>;
}
return (
<div className="App">
<h1>
This is a Demo showing several ways to implement Conditional Rendering in React.
</h1>
{AuthButton}
</div>
);
}
...
註意我們如何有條件地將值(組件)分配給AuthButton
,然後我們只需要在JSX中渲染它即可。
3. 使用switch語句
如前所示,我們可以使用if…else語句根據設置的條件從組件返回不同的標簽。使用switch語句也可以達到相同的效果,在該語句中我們可以為不同的條件指定標簽。看看如下代碼:
// AuthButton.js
import React from "react";
const AuthButton = props => {
let { isLoggedIn } = props;
switch (isLoggedIn) {
case true:
return <button>Logout</button>;
break;
case false:
return <button>Login</button>;
break;
default:
return null;
}
};
export default AuthButton;
註意我們如何根據isLoggedIn
的值返回不同的按鈕。當存在兩個以上可能的值或結果時,採用此方法更為合理。你也可以通過break語句取消,正如return語句自動終止執行一樣。
註意:從組件返回null
會使它隱藏自身/不顯示任何內容。這是切換組件可見性的好方法。
4. 三元運算符
如果你熟悉三元運算符,那麼你應該知道這是編寫if語句的一種更簡潔的方法。因此我們也許會這樣寫:
// index.js
...
render() {
let { isLoggedIn } = this.state;
return (
<div className="App">
<h1>
This is a Demo showing several ways to implement Conditional Rendering
in React.
</h1>
{isLoggedIn ? <button>Logout</button> : <button>Login</button>}
</div>
);
}
...
但在上例中,這種方法會使組件臃腫,笨重和難以理解,你可以將條件封裝在純函數組件中。如下所示:
// AuthButton.js
import React from "react";
const AuthButton = props => {
let { isLoggedIn } = props;
return isLoggedIn ? <button>Logout</button> : <button>Login</button>;
};
export default AuthButton;
5. 邏輯運算符&&
短路運算是一種用於確保在表達式運算過程中沒有副作用的技術。邏輯&&幫助我們指定僅在一種情況下執行,否則將被完全忽略。這對於僅在特定條件為真時才需要執行的情況下是很有用的。
例如,如果是登錄狀態,我們只需顯示Logout
按鈕,否則我們什麼也不做。如下:
// index.js
...
render() {
let { isLoggedIn } = this.state;
return (
<div className="App">
<h1>
This is a Demo showing several ways to implement Conditional Rendering
in React.
</h1>
{isLoggedIn && <button>Logout</button>}
</div>
);
}
...
如果isLoggedIn
為true,則將顯示Logout
按鈕,否則將不顯示任何內容。我們用相同方法就可以實現最終結果,如下所示。
// index.js
...
return (
<div className="App">
<h1>
This is a Demo showing several ways to implement Conditional Rendering
in React.
</h1>
{isLoggedIn && <button>Logout</button>}
{!isLoggedIn && <button>Login</button>}
</div>
);
...
這是基於isLoggedIn
的值渲染正確的按鈕。但是,不建議這樣做,因為有更好、更清潔的方法可以達到相同的效果。而且,一旦組件稍大一些,這很容易使你代碼看起來混亂和難以理解。
6. 使用立即調用函數表達式(IIFE)
還記的剛纔說的JSX局限性嗎,在其中無法執行所有JavaScript代碼。嗯...這並不完全正確的,因為有很多方法可以繞過這種行為。一種方法是使用IIFE。
(function () {
statements
})();
點擊鏈接瞭解更多
通過這種技術,我們能夠直接在JSX內編寫條件邏輯,但將其包裝在匿名函數中,該匿名函數在運行該部分代碼後立即被調用。請參見下麵的示例:
//index.js
...
render() {
let { isLoggedIn } = this.state;
return (
<div className="App">
<h1>
This is a Demo showing several ways to implement Conditional Rendering
in React.
</h1>
{(function() {
if (isLoggedIn) {
return <button>Logout</button>;
} else {
return <button>Login</button>;
}
})()}
</div>
);
}
...
也可以使用箭頭功能,通過更加簡潔的方式編寫該代碼,如下所示:
// index.js
...
return (
<div className="App">
<h1>
This is a Demo showing several ways to implement Conditional Rendering in React.
</h1>
{(()=> {
if (isLoggedIn) {
return <button>Logout</button>;
} else {
return <button>Login</button>;
}
})()}
</div>
);
...
7. 使用增強的JSX
某些庫公開了擴展JSX的功能,因此可以直接用JSX實現條件渲染。此類庫之一是JSX Control Statements。它是Babel插件,可在編譯過程中將類似組件的控制語句轉換為JavaScript對應的語句。請參閱下麵的示例以瞭解如何實現。
// index.js
...
return (
<div className="App">
<h1>
This is a Demo showing several ways to implement Conditional Rendering in React.
</h1>
<Choose>
<When condition={isLoggedIn}>
<button>Logout</button>;
</When>
<When condition={!isLoggedIn}>
<button>Login</button>;
</When>
</Choose>
</div>
);
...
但是,不建議使用這種方法,因為您編寫的代碼最終會轉換為常規JavaScript條件。僅僅編寫JavaScript可能總比對如此瑣碎的事情增加額外的依賴要好。
性能問題
作為通用規則,最好確保在實現條件渲染時:
- 請勿隨意更改組件的位置,以防止不必要地卸卸和重載組件。
- 僅更改與條件渲染有關的標簽,而不改變組件中沒有變動的部分。
- 不要在render方法中使組件不必要的臃腫,從而導致組件延遲渲染。
總結
我們已經成功研究了在React中實現條件渲染的7種方法。每種方法都有其自身的優勢,選擇哪種方法主要取決於實際情況。要考慮的事項包括:
- 條件渲染標簽的大小
- 可能結果的數目
- 哪個會更直觀和可讀
通常,我建議:
- 當只有一個預期的結果時,使用邏輯&&運算符非常方便。
- 對於布爾型情況或只有兩個可能結果的用例,可以使用if…else,Element變數,三元運算符和IIFE。
- 如果結果超過2個,則可以使用Switch語句,提取成函數或提取成純函數組件。
但是,這些僅是建議,最終還是根據實際情況選擇。