zoukankan      html  css  js  c++  java
  • 【译】在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…elseElement变量三元运算符IIFE
    • 如果结果超过2个,则可以使用Switch语句提取成函数或提取成纯函数组件

    但是,这些仅是建议,最终还是根据实际情况选择。

  • 相关阅读:
    虚拟机安装配置
    大整数加法 面试题
    结构体
    操作文件
    Gcd HDU
    牛客练习赛47 A DongDong破密码 (异或性质,递推)
    ACM常用之 异或运算的性质。
    Wannafly挑战赛22 C 多项式(大数,多项式极限)
    大数全能模板
    Wannafly挑战赛22 D 整数序列 (线段树维护三角函数值)
  • 原文地址:https://www.cnblogs.com/hanksyao/p/12066412.html
Copyright © 2011-2022 走看看