条件渲染,就是根据不同条件决定渲染哪些内容。在 React 的 JSX 条件下,条件渲染其实没有引入任何新的关键字,而是直接使用了 JS 语言的 if ,&& ,以及三元运算等原生语法。

if 条件渲染

先看一个使用 If 的例子。

index.js

import React from 'react'
import ReactDOM from 'react-dom'

const UserGreeting = () => <h1>Welcome back!</h1>

const GuestGreeting = () => <h1>Please sign up.</h1>

const Greeting = props => {
  const isLoggedIn = props.isLoggedIn
  if (isLoggedIn) {
    return <UserGreeting />
  }
  return <GuestGreeting />
}

ReactDOM.render(<Greeting isLoggedIn={true} />, document.getElementById('root'))

先定义两个函数式组件,一个是跟已经等录的用户打招呼,另一个跟访客打招呼。下面定义 Greeting 组件。随着 isLoggedIn 的值的不同,会显示出不同的内容。

浏览器中,当 isLoggedIn 设置为 true 和 false ,会分别显示不同的打招呼信息。

这就是通过 if 语句来实现条件渲染的方式。完全 No surprise .

元素变量

要灵活使用条件渲染,很常用的一个技巧是,把一些元素保存到一个变量中,这样的变量叫做元素变量。元素变量在条件渲染过程中非常有用,因为可以通过它来条件渲染组件的一部分,而保持另外的一部分不变。

import React, { Component } from 'react'
import ReactDOM from 'react-dom'

const UserGreeting = () => <h1>Welcome Back</h1>
const GuestGreeting = () => <h1>Please Sign Up</h1>
const LoginButton = props => <button onClick={props.onClick}>Login</button>
const LogoutButton = props => <button onClick={props.onClick}>Logout</button>

const Greeting = props => {
  const { isLoggedIn } = props
  if (isLoggedIn) {
    return <UserGreeting />
  }
  return <GuestGreeting />
}

class LoginControl extends Component {
  state = {
    isLoggedIn: false
  }

  handleLoginClick = () => {
    this.setState({
      isLoggedIn: true
    })
  }
  handleLogoutClick = () => {
    this.setState({
      isLoggedIn: false
    })
  }

  render() {
    const { isLoggedIn } = this.state

    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'))

添加两个按钮组件进来,一个是登录,一个是登出。创建一个 LoginControl 组件,初始化 isLoggedIn ,添加登录和登出对应的处理函数,里面对 isLoggedIn 状态值进行了修改。

render() 函数中使用 isLoggedIn 状态值。定义 button 变量,注意,button 就是一个元素变量了,因为我们会用它来保存元素。根据 isLoggedIn 的值决定 button 到底赋值为哪个按钮,下面 Greeting 组件传入 isLoggedIn ,button 变量写到它下面,语法上看上去简单明了。

浏览器中,点按钮, button 和 Greeting 组件都可以正确的切换状态。

&& 和三元条件运算符实现条件渲染

if 这种方式比较强大,但是写起来通常要占用多行,有时候稍显复杂,下面看看在行内解决条件判断的方式。具体而言就是用 && 号或者三元条件运算符,实现 if 效果。

import React from 'react'
import ReactDOM from 'react-dom'

const Mailbox = props => {
  const { unreadMessages } = props
  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')
)

定义 Mailbox 组件,属性中拿到未读邮件的数组,下面用 && 号实现 if 的效果,如果未读邮件数量大于 0,就显示未读邮件的数量。数量为 0,&& 左侧内容求值为 false ,那么右侧也就不会执行了,也就是什么都不会显示了。

下面定义,邮件数组 messages ,传入 Mailbox 组件。

浏览器中,看到可以显示未读邮件的数量。

类似的,可以使用条件运算符,或者叫三元运算符,来实现行内的 if else 效果。

      {unreadMessages.length > 0 ? <h2>You have {unreadMessages.length} unread messages.</h2> : <h2>0 message</h2> }

如果,未读邮件数量为零的时候,我们也希望能显示一定信息,那就可以用三元条件运算符了。这种写法明显比 if else 的形式要少些不少字符。

好,关于 && 和三元条件运算符的内容就介绍到这里。

总结

这集咱们聊条件渲染,主体内容就是这些了。重点内容有:第一,JSX 下实现条件渲染就是使用 JS 的基本语法。第二,元素变量这个概念是灵活使用条件渲染必须要理解的。第三,除了 if ,条件渲染还可以用更加简洁的 && 和三元条件运算符来达成。

参考