在React中实现条件渲染的7种方法

更新日期: 2019-11-20阅读: 1.7k标签: 渲染

借助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语句提取成函数或提取成纯函数组件

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


链接: https://www.fly63.com/article/detial/6943

vue中数据更新变化,而页面视图未渲染的解决方案

在使用vue的时候,我们都知道它是双向数据绑定的,但是在使用不熟的情况下,经常会遇到:data中的数据变化了,但是并没有触发页面渲染。下面就整理一些出现这种情况的场景以及解决办法。

服务端渲染和客户端渲染的对比

这里结合art-template模板引擎说明。首先了解下前端页面中如何使用art-template。当不需要对SEO友好的时候,推荐使用客户端渲染;当需要对 SEO友好的时候,推荐使用服务器端渲染

解决使用vue.js未渲染前代码显示问题

在使用vue的时候,偶然发现多次刷新或者网络加载缓慢的时候,会一瞬间出现设置的模板的情况。实在很影响美观,可以使用vue现成的指令来解决这个问题:v-cloak

在微信小程序中渲染html内容的实现

大部分Web应用的富文本内容都是以HTML字符串的形式存储的,通过HTML文档去展示HTML内容自然没有问题。但是,在微信小程序(下文简称为「小程序」)中,应当如何渲染这部分内容呢?

原来 CSS 与 JS 是这样阻塞 DOM 解析和渲染的

估计大家都听过,尽量将 CSS 放头部,JS 放底部,这样可以提高页面的性能。然而,为什么呢?大家有考虑过么?很长一段时间,我都是知其然而不知其所以然,强行背下来应付考核当然可以,但实际应用中必然一塌糊涂

Vue渲染数据理解以及Vue指令

原生JS改变页面数据,必须要获取页面节点,也即是进行DOM操作,jQuery之类的框架只是简化DOM操作的写法,实质并没有改变操作页面数据的底层原理,DOM操作影响性能(导致浏览器的重绘和回流),Vue是一个mvvm框架(库),大幅度减少了DOM操作

Web渲染那些事儿

在决定渲染方式时,需要测量和理解真正的瓶颈在哪里。静态渲染或服务器渲染在多数情况都比较适用,尤其是可交互性对JS依赖较低的场景。下面是一张便捷的信息图,显示了服务器到客户端的技术频谱:

vue从后台获取数据赋值给data,如何渲染更细视图

如果从服务端返回的数据量较少,或者只有几个字段,可以用vue的set方法,如果数据量较大,请直接看第二种情况。官网API是这样介绍的:Vue.set(target,key,value)

react 异步加载数据时的渲染问题

当数据需要异步加载时render获取不到数据可能会报一些错误,此时需要在render函数中加一个判断.行到render时,state对象的haveData为false, 所以此时页面展示 loading,当异步获取数据成功时

Vue.js中v-html渲染的dom添加scoped的样式

在vue.js中,要将一段字符串渲染成html,可以使用v-html指令。但是 官方文档 中的v-html部分也提醒了

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!