🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 条件渲染 在 React 中,你可以创建不同的组件封装你需要的行为。然后,只渲染它们之中的一些,取决于你的应用的状态。 React 中的条件渲染就和在 JavaScript 中的条件控制一样。使用 JavaScript 操作符如 [if](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else) 或者[条件操作符](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Conditional_Operator)来创建渲染当前状态的元素,使 React 更新匹配的 UI 。 思考这两个组件: ~~~ function UserGreeting(props) { return <h1>Welcome back!</h1>; } function GuestGreeting(props) { return <h1>Please sign up.</h1>; } ~~~ 我们将创建一个 Greeting 组件来显示这两个组件之一,根据用户是否已经登录: ~~~ function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn) { return <UserGreeting />; } return <GuestGreeting />; } ReactDOM.render( // 尝试修改 isLoggedIn={true}: <Greeting isLoggedIn={false} />, document.getElementById('root') ); ~~~ 在 CodePen 中[打开查看](https://codepen.io/gaearon/pen/ZpVxNq?editors=0011)。 这个例子根据 isLoggedIn prop 渲染了不同的问候语 。 ## 元素变量 可以用变量来存储元素。这可以在其它的输出没有改变的时候帮你条件渲染部分组件。 思考这两个代表 Logout 和 Login 按钮的两个新的组件: ~~~ function LoginButton(props) { return ( <button onClick={props.onClick}> Login </button> ); } function LogoutButton(props) { return ( <button onClick={props.onClick}> Logout </button> ); } ~~~ 在这个例子中,我们将会创建一个有状态组件,叫做 LoginControl。 它将渲染 `<LoginButton />` 或者 `<LogoutButton />`,取决于当前状态。它也会从前面的例子中渲染一个 `<Greeting />`: ~~~ class LoginControl extends React.Component { constructor(props) { super(props); this.handleLoginClick = this.handleLoginClick.bind(this); this.handleLogoutClick = this.handleLogoutClick.bind(this); this.state = {isLoggedIn: false}; } handleLoginClick() { this.setState({isLoggedIn: true}); } handleLogoutClick() { this.setState({isLoggedIn: false}); } render() { const isLoggedIn = this.state.isLoggedIn; let button = null; if (isLoggedIn) { button = <LogoutButton onClick={this.handleLogoutClick} />; } else { button = <LoginButton onClick={this.handleLoginClick} />; } return ( <div> <Greeting isLoggedIn={isLoggedIn} /> {button} </div> ); } } ReactDOM.render( <LoginControl />, document.getElementById('root') ); ~~~ 在 CodePen 中[打开查看](https://codepen.io/gaearon/pen/QKzAgB?editors=0010)。 虽然声明一个变量并使用一个 if 语句是对组件进行条件渲染的好方法,但有时你可能希望使用一个更短的语法。在 JSX 中还有一些内联的条件用法,下面进行解释。 ## 使用逻辑 && 操作符的内联 if 用法 在[ JSX 中你可以嵌入任何表达式到花括号](https://facebook.github.io/react/docs/introducing-jsx.html#embedding-expressions-in-jsx)中。也包括 JavaScript 的逻辑 && 操作符。这在一个元素中进行条件编写是非常方便的: ~~~ function Mailbox(props) { const unreadMessages = props.unreadMessages; return ( <div> <h1>Hello!</h1> {unreadMessages.length > 0 && <h2> You have {unreadMessages.length} unread messages. </h2> } </div> ); } const messages = ['React', 'Re: React', 'Re:Re: React']; ReactDOM.render( <Mailbox unreadMessages={messages} />, document.getElementById('root') ); ~~~ 在 CodePen 中[打开查看](https://codepen.io/gaearon/pen/ozJddz?editors=0010)。 它可以正常运行,因为在 JavaScript 中, true && 表达式总是会执行为 expression,而 false && expression 总是执行为 false 。 因此,如果条件为 true ,&& 之后的元素会在输出中显示。如果为 false,React 将会忽略并跳过它。 ## 使用条件操作符的内联 if...else 另一个用于条件渲染元素的内联方法是使用 JavaScript 的条件操作符 [condition ? true : false](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) 。 在这个例子中,我们使用它来进行条件渲染一个小的文本块: ~~~ render() { const isLoggedIn = this.state.isLoggedIn; return ( <div> The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in. </div> ); } ~~~ 还可以用于较大的表达式,即使它不太明显接下来的行为: ~~~ render() { const isLoggedIn = this.state.isLoggedIn; return ( <div> {isLoggedIn ? ( <LogoutButton onClick={this.handleLogoutClick} /> ) : ( <LoginButton onClick={this.handleLoginClick} /> )} </div> ); } ~~~ 就像在 JavaScript 中,这取决于你选择一个认为适合你和你的团队认为更加好用的方式。另外要记得,无论何时条件变得复杂时,是时候来提取一个组件了。 ## 在组件中防止渲染 在某些少用的场景,你可能需要一个组件隐藏自己,即使它是被另一个组件渲染的。可以通过 return null 而不是返回它的渲染输出来实现。 在下面的例子中, `<WarningBanner />` 是否渲染,取决于一个叫做 warn 的prop 的值。如果值是 false,那么组件不会被渲染: ~~~ function WarningBanner(props) { if (!props.warn) { return null; } return ( <div className="warning"> Warning! </div> ); } class Page extends React.Component { constructor(props) { super(props); this.state = {showWarning: true} this.handleToggleClick = this.handleToggleClick.bind(this); } handleToggleClick() { this.setState(prevState => ({ showWarning: !prevState.showWarning })); } render() { return ( <div> <WarningBanner warn={this.state.showWarning} /> <button onClick={this.handleToggleClick}> {this.state.showWarning ? 'Hide' : 'Show'} </button> </div> ); } } ReactDOM.render( <Page />, document.getElementById('root') ); ~~~ 在 CodePen 中[打开查看](https://codepen.io/gaearon/pen/Xjoqwm?editors=0010)。