vuepress-theme-vdoing/docs/《React》笔记/01.核心概念/06.条件渲染.md

233 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 条件渲染
date: 2021-03-24 17:56:40
permalink: /pages/8fcda8/
categories:
- 《React》笔记
- 核心概念
tags:
- React
author:
name: xugaoyi
link: https://github.com/xugaoyi
---
# 06. 条件渲染
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。
观察这两个组件:
```jsx
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
```
再创建一个 `Greeting` 组件,它会根据用户是否登录来决定显示上面的哪一个组件。
```jsx
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
// 根据条件来渲染组件(UI)
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
// Try changing to isLoggedIn={true}:
<Greeting isLoggedIn={false} />,
document.getElementById('root')
);
```
## 元素变量
你可以使用变量来储存元素。 它可以帮助你有条件地渲染组件的一部分,而其他的渲染部分并不会因此而改变。
```jsx
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;
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)
> 此方式有些复杂~
## 与运算符 &&
通过花括号包裹代码,你可以[在 JSX 中嵌入表达式](https://zh-hans.reactjs.org/docs/introducing-jsx.html#embedding-expressions-in-jsx)。这也包括 JavaScript 中的逻辑与 (&&) 运算符。它可以很方便地进行元素的条件渲染:
```jsx
function Mailbox(props){
const unreadMeg = props.unreadMeg
return (
<div>
{
unreadMeg.length &&
<h2>You have {unreadMeg.length} unread messages</h2>
}
</div>
)
}
const meg = ['1','22','33']
ReactDOM.render(
<Mailbox unreadMeg={meg} />,
document.getElementById('root')
)
```
如果条件是 `true``&&` 右侧的元素就会被渲染,如果是 `false`React 会忽略并跳过它。
请**注意**,返回 false 的表达式会使 `&&` 后面的元素被跳过,但会返回 false 表达式。在下面示例中render 方法的返回值是 `<div>0</div>`
```jsx
render() {
const count = 0;
return (
<div>
// 这里会渲染count的值
{ count && <h1>Messages: {count}</h1>}
</div>
);
}
```
## 三目运算符
```jsx
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
</div>
);
}
```
```jsx
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{isLoggedIn
? <LogoutButton onClick={this.handleLogoutClick} />
: <LoginButton onClick={this.handleLoginClick} />
}
</div>
);
}
```
> 可通过三目运算符来条件渲染相应组件。
## 阻止组件渲染
通过让 `render` 方法直接返回 `null`阻止渲染:
```jsx
function WarningBanner(props) {
if (!props.warn) {
// 返回null则不渲染此组件
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(state => ({
showWarning: !state.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')
);
```
在组件的 `render` 方法中返回 `null` 并不会影响组件的生命周期。例如,上面这个示例中,`componentDidUpdate` 依然会被调用。