【译】在React中实现条件渲染的7种方法
原文地址: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语句,提取成函数或提取成纯函数组件。
但是,这些仅是建议,最终还是根据实际情况选择。
【译】在React中实现条件渲染的7种方法的更多相关文章
- 好客租房15-jsx中的条件渲染
jsx中的条件渲染 场景:loding效果 条件渲染:根据条件渲染特定的jsx结构 可以使用if/else或者三元运算符和逻辑和运算符实现 //导入react import React from &q ...
- 浅析Vue.js 中的条件渲染指令
1 应用于单个元素 Vue.js 中的条件渲染指令可以根据表达式的值,来决定在 DOM 中是渲染还是销毁元素或组件. html: <div id="app"> < ...
- AE控制图层中要素可见状态的几种方法
转自原文 AE控制图层中要素可见状态的几种方法 工作中常有这样的需求,一个作业图层由几个作业员来操作,我们要 控制每一个作业员只能看到他负责的区域.作业员的可见区域控制有时候是按空间区域划分,有时候是 ...
- 在React中跨组件分发状态的三种方法
在React中跨组件分发状态的三种方法 当我问自己第一百次时,我正在研究一个典型的CRUD屏幕:"我应该将状态保留在这个组件中还是将其移动到父组件?". 如果需要对子组件的状态进行 ...
- 在Oracle中执行动态SQL的几种方法
转载:在Oracle中执行动态SQL的几种方法 以下为内容留存: 在Oracle中执行动态SQL的几种方法 在一般的sql操作中,sql语句基本上都是固定的,如:SELECT t.empno,t.en ...
- .net中创建xml文件的两种方法
.net中创建xml文件的两种方法 方法1:根据xml结构一步一步构建xml文档,保存文件(动态方式) 方法2:直接加载xml结构,保存文件(固定方式) 方法1:动态创建xml文档 根据传递的值,构建 ...
- Java中获取键盘输入值的三种方法
Java中获取键盘输入值的三种方法 Java程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值 ...
- Web Service 中返回DataSet结果的几种方法
Web Service 中返回DataSet结果的几种方法: 1)直接返回DataSet对象 特点:通常组件化的处理机制,不加任何修饰及处理: 优点:代码精减.易于处理,小数据量处理较快: ...
- Oracle中获取执行计划的几种方法分析
以下是对Oracle中获取执行计划的几种方法进行了详细的分析介绍,需要的朋友可以参考下 1. 预估执行计划 - Explain PlanExplain plan以SQL语句作为输入,得到这条S ...
随机推荐
- 在Raspberry Pi上创建容器
树莓派Raspbian默认是支持LXC容器的,下面我们介绍一下在树莓派上创建并运行容器的过程. 1. 安装LXC相关的package $ sudo apt-get install -y git lxc ...
- python--debug神器pysnooper
使用它你可以获得什么优势: (1)无需用print就可以获得变量的值: (2)以日志地形式进行保存,方便随时查看: (3)可以根据需要,设置调用函数的深度: (4)多个函数的日志,可以设置前缀进行标识 ...
- C#Windows Forms 使MessageBox顶层显示--xdd
方法1. MessageBox.Show("Text", "Caption", MessageBoxButtons.OK, MessageBoxIcon.Inf ...
- 附012.Kubeadm部署高可用Kubernetes
一 kubeadm介绍 1.1 概述 参考<附003.Kubeadm部署Kubernetes>. 1.2 kubeadm功能 参考<附003.Kubeadm部署Kubernetes& ...
- C语言I博客作业10
这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-1/homework/10095 我在这个课程的 ...
- Docker harbor 安装和基础操作
目录 简介 离线安装 配置文件 安装 查看 访问测试 及 简单操作 创建一个用户 创建一个测试仓库 创建测试仓库 测试上传和下载镜像 上传 下载镜像测试 简介 Docker容器应用的开发和运行离不开可 ...
- libgcc_s.so.1 cannot open shared object file No such file or directory
libgcc_s.so.1: cannot open shared object file: No such file or directory解决办法 背景 使用WAR包安装jenkins,在tom ...
- 【并发编程】关于Thread类的详细介绍
多线程编程基础--Thread类 Thread类是Java中实现多线程编程的基础类.本篇博客就来介绍下Thread类的常用API和常见用法. Thread类常用的方法如下: Thread.active ...
- 浅谈C#中的序列化与反序列化
今天我利用这篇文章给大家讲解一下C#中的序列化与反序列化.这两个概念我们再开发中经常用到,但是我们绝大部分只用到了其中的一部分,剩下的部分很多开发人员并不清楚,甚至可以说是不知道.因此我希望通过这篇文 ...
- shell ssh 远程机器 追加文件内容
在host1上,把下面的两行内容通过ssh追加到host2上的/etc/ca-certificates.conf文件中 I am a student Are you ok ssh host2 &quo ...