如何具有条件元素并保持Facebook React的JSX的DRY?

2020/10/12 08:01 · javascript ·  · 0评论

如何在JSX中选择性地包含元素?这是一个使用横幅的示例,如果已传递该横幅,则该横幅应位于组件中。我要避免的是必须在if语句中复制HTML标签。

render: function () {
    var banner;
    if (this.state.banner) {
        banner = <div id="banner">{this.state.banner}</div>;
    } else {
        banner = ?????
    }
    return (
        <div id="page">
            {banner}
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

只需将横幅标为未定义即可,它就不会包含在内。

那这个呢。让我们定义一个简单的帮助If组件。

var If = React.createClass({
    render: function() {
        if (this.props.test) {
            return this.props.children;
        }
        else {
            return false;
        }
    }
});

并以这种方式使用它:

render: function () {
    return (
        <div id="page">
            <If test={this.state.banner}>
                <div id="banner">{this.state.banner}</div>
            </If>
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

更新:随着我的答案越来越流行,我有义务警告您有关此解决方案的最大危险。正如另一个答案中指出的那样<If />,无论条件是true还是false,始终都会执行组件内部的代码因此,下面的示例将在壳体的失败bannernull(注意在第二行上的属性访问):

<If test={this.state.banner}>
    <div id="banner">{this.state.banner.url}</div>
</If>

使用时必须小心。我建议阅读其他答案,以寻求替代(更安全)的方法。

更新2:回头看,这种方法不仅危险,而且非常麻烦。这是一个典型的示例,说明当开发人员(我)试图将他所知道的模式和方法从一个领域转移到另一个领域,但实际上并没有用(在这种情况下,是其他模板语言)。

如果需要条件元素,请按照以下步骤操作:

render: function () {
    return (
        <div id="page">
            {this.state.banner &&
                <div id="banner">{this.state.banner}</div>}
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

如果您还需要else分支,只需使用三元运算符:

{this.state.banner ?
   <div id="banner">{this.state.banner}</div> :
   <div>There is no banner!</div>
}

它更短,更优雅,更安全。我用它所有的时间。唯一的缺点是您无法else if轻松地进行分支,但这通常并不常见。

无论如何,这要归功于JavaScript中逻辑运算符的工作方式。逻辑运算符甚至允许以下小技巧:

<h3>{this.state.banner.title || 'Default banner title'}</h3>

就我个人而言,我真的认为(JSX In Depth)中显示的三元表达式是符合ReactJs标准的最自然的方式。

请参见以下示例。乍一看有点混乱,但效果很好。

<div id="page">
  {this.state.banner ? (
    <div id="banner">
     <div class="another-div">
       {this.state.banner}
     </div>
    </div>
  ) : 
  null} 
  <div id="other-content">
    blah blah blah...
  </div>
</div>

您也可以这样写

{ this.state.banner && <div>{...}</div> }

如果您state.bannernullundefined,则跳过条件的右侧。

If样式组件是危险的,因为该代码块总是执行不管条件的。例如,如果banneris ,这将导致null异常null

//dangerous
render: function () {
  return (
    <div id="page">
      <If test={this.state.banner}>
        <img src={this.state.banner.src} />
      </If>
      <div id="other-content">
         blah blah blah...
      </div>
    </div>
  );
}

另一种选择是使用内联函数(对else语句特别有用):

render: function () {
  return (
    <div id="page">
      {function(){
        if (this.state.banner) {
          return <div id="banner">{this.state.banner}</div>
        }
      }.call(this)}
      <div id="other-content">
         blah blah blah...
      </div>
    </div>
  );
}

解决问题的另一种选择

render: function () {
  return (
    <div id="page">
      { this.state.banner &&
        <div id="banner">{this.state.banner}</div>
      }
      <div id="other-content">
         blah blah blah...
      </div>
    </div>
  );
}

&& +代码样式+小组件

对于我来说,这种简单的测试语法+代码样式约定+小组件是最容易阅读的选项。你只需要特别照顾的falsy值喜欢false0""

render: function() {
    var person= ...; 
    var counter= ...; 
    return (
       <div className="component">
          {person && (
            <Person person={person}/>
          )}
          {(typeof counter !== 'undefined') && (
            <Counter value={counter}/>
          )}
       </div>
    );
}

做记号

ES7的stage-0注释符号语法也非常好,当我的IDE正确支持它时,我将明确使用它:

const Users = ({users}) => (
  <div>
    {users.map(user =>
      <User key={user.id} user={user}/>
    )}
  </div>
)  

const UserList = ({users}) => do {
  if (!users) <div>Loading</div>
  else if (!users.length) <div>Empty</div>
  else <Users users={users}/>
}

此处有更多详细信息:ReactJs-创建一个“ If”组件...一个好主意?

简单,创建一个函数。

renderBanner: function() {
  if (!this.state.banner) return;
  return (
    <div id="banner">{this.state.banner}</div>
  );
},

render: function () {
  return (
    <div id="page">
      {this.renderBanner()}
      <div id="other-content">
        blah blah blah...
      </div>
    </div>
  );
}

我一直以来都遵循这种模式。使代码真正干净且易于理解。此外,Banner如果它变得太大(或在其他地方重复使用),它还允许您将重构为自己的组件。

实验性的ES7do语法使此操作变得容易。如果您使用的是Babel,请启用该es7.doExpressions功能,然后:

render() {
  return (
    <div id="banner">
      {do {
        if (this.state.banner) {
          this.state.banner;
        } else {
          "Something else";
        }
      }}
    </div>
  );
}

参见http://wiki.ecmascript.org/doku.php?id=strawman:do_expressions

正如答案中已经提到的,JSX为您提供了两种选择

  • 三元运算符

    { this.state.price ? <div>{this.state.price}</div> : null }

  • 逻辑合取

    { this.state.price && <div>{this.state.price}</div> }


但是,这些功能不适用于 price == 0

JSX将在第一种情况下呈现false分支,在逻辑合取的情况下,将不呈现任何内容。如果该属性可能为0,则只需在JSX之外使用if语句即可。

当“ if”分支中有多个元素时,此组件有效:

var Display = React.createClass({
  render: function () {
    if (!this.props.when) {
      return false;
    }
    return React.DOM.div(null, this.props.children);
  },
});

用法:

render: function() {
  return (
    <div>
      <Display when={this.state.loading}>
        Loading something...
        <div>Elem1</div>
        <div>Elem2</div>
      </Display>
      <Display when={!this.state.loading}>
        Loaded
        <div>Elem3</div>
        <div>Elem4</div>
      </Display>
    </div>
  );
}

ps有人认为这些组件不利于代码阅读。但是在我看来,带有javascript的HTML更糟

大多数示例都带有一行有条件呈现的“ html”。当我有多行需要有条件地呈现时,这对我来说似乎可读。

render: function() {
  // This will be renered only if showContent prop is true
  var content = 
    <div>
      <p>something here</p>
      <p>more here</p>
      <p>and more here</p>
    </div>;

  return (
    <div>
      <h1>Some title</h1>

      {this.props.showContent ? content : null}
    </div>
  );
}

第一个例子很好,因为代替null我们可以有条件地渲染其他一些内容,例如{this.props.showContent ? content : otherContent}

但是,如果您只需要显示/隐藏内容,这会更好,因为忽略了布尔值,空值和未定义

render: function() {
  return (
    <div>
      <h1>Some title</h1>

      // This will be renered only if showContent prop is true
      {this.props.showContent &&
        <div>
          <p>something here</p>
          <p>more here</p>
          <p>and more here</p>
        </div>
      }
    </div>
  );
}

还有另外一个解决方案,如果是React的组件

var Node = require('react-if-comp');
...
render: function() {
    return (
        <div id="page">
            <Node if={this.state.banner}
                  then={<div id="banner">{this.state.banner}</div>} />
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

我使用一个更明确的快捷方式:立即调用函数表达式(IIFE):

{(() => {
  if (isEmpty(routine.queries)) {
    return <Grid devices={devices} routine={routine} configure={() => this.setState({configured: true})}/>
  } else if (this.state.configured) {
    return <DeviceList devices={devices} routine={routine} configure={() => this.setState({configured: false})}/>
  } else {
    return <Grid devices={devices} routine={routine} configure={() => this.setState({configured: true})}/>
  }
})()}

也许它可以帮助遇到以下问题的人:React中的所有条件渲染这是一篇有关的所有不同选项的文章。

何时使用哪种条件渲染的关键要点:

** 如果别的

  • 是最基本的条件渲染
  • 初学者友好
  • 使用if是否通过返回null提前退出渲染方法

**三元运算符

  • 在if-else语句上使用它
  • 比if-else更简洁

**逻辑&&运算符

  • 当三元运算的一侧返回null时使用它

**开关盒

  • 冗长的
  • 只能内联自调用功能
  • 避免它,使用枚举代替

**枚举

  • 完美地映射不同的状态
  • 完美地映射多个条件

**多级/嵌套条件渲染

  • 出于可读性考虑,避免使用它们
  • 使用自己的简单条件渲染将组件拆分为更轻量的组件
  • 使用HOC

** HOC

  • 用它们来屏蔽条件渲染
  • 组件可以专注于其主要目的

**外部模板组件

  • 避免使用它们,并熟悉JSX和JavaScript

我做了https://www.npmjs.com/package/jsx-control-statements,使其更容易一点,基本上它允许你定义<If>条件语句作为标签,然后将其编译成三元IFS,使内部的代码<If>只得到如果条件为真,则执行。

还有一个非常干净的单行版本... {this.props.product.title || “无题” }

即:

render: function() {
            return (
                <div className="title">
                    { this.props.product.title || "No Title" }
                </div>
            );
        }

最近做了https://github.com/ajwhite/render-if,仅在谓词通过时安全地呈现元素

{renderIf(1 + 1 === 2)(
  <span>Hello!</span>
)}

要么

const ifUniverseIsWorking = renderIf(1 + 1 === 2);

//...

{ifUniverseIsWorking(
  <span>Hello!</span>
)}

您可以使用三元运算符有条件地包含元素,如下所示:

render: function(){

         return <div id="page">

                  //conditional statement
                  {this.state.banner ? <div id="banner">{this.state.banner}</div> : null}

                  <div id="other-content">
                      blah blah blah...
                  </div>

               </div>
}

您可以使用一个函数并返回组件并保持较薄的渲染功能

class App extends React.Component {
  constructor (props) {
    super(props);
    this._renderAppBar = this._renderAppBar.bind(this);
  }

  render () {
    return <div>
      {_renderAppBar()}

      <div>Content</div>

    </div>
  }

  _renderAppBar () {
    if (this.state.renderAppBar) {
      return <AppBar />
    }
  }
}

这是我使用ES6的方法。

import React, { Component } from 'react';
// you should use ReactDOM.render instad of React.renderComponent
import ReactDOM from 'react-dom';

class ToggleBox extends Component {
  constructor(props) {
    super(props);
    this.state = {
      // toggle box is closed initially
      opened: false,
    };
    // http://egorsmirnov.me/2015/08/16/react-and-es6-part3.html
    this.toggleBox = this.toggleBox.bind(this);
  }

  toggleBox() {
    // check if box is currently opened
    const { opened } = this.state;
    this.setState({
      // toggle value of `opened`
      opened: !opened,
    });
  }

  render() {
    const { title, children } = this.props;
    const { opened } = this.state;
    return (
      <div className="box">
        <div className="boxTitle" onClick={this.toggleBox}>
          {title}
        </div>
        {opened && children && (
          <div class="boxContent">
            {children}
          </div>
        )}
      </div>
    );
  }
}

ReactDOM.render((
  <ToggleBox title="Click me">
    <div>Some content</div>
  </ToggleBox>
), document.getElementById('app'));

演示:http : //jsfiddle.net/kb3gN/16688/

我正在使用类似的代码:

{opened && <SomeElement />}

SomeElement仅当opened为true时才会渲染它之所以有效,是因为JavaScript如何解析逻辑条件:

true && true && 2; // will output 2
true && false && 2; // will output false
true && 'some string'; // will output 'some string'
opened && <SomeElement />; // will output SomeElement if `opened` is true, will output false otherwise

至于React会忽略false,我觉得它有条件地呈现一些元素很好的办法。

使用ES6,您可以使用简单的一线操作

const If = ({children, show}) => show ? children : null

“显示”是一个布尔值,您可以通过以下方式使用此类

<If show={true}> Will show </If>
<If show={false}> WON'T show </div> </If>

我认为这没有被提及。这就像您自己的答案,但我认为它甚至更简单。您始终可以从表达式返回字符串,并且可以将jsx嵌套在表达式中,因此这使内联表达式易于阅读。

render: function () {
    return (
        <div id="page">
            {this.state.banner ? <div id="banner">{this.state.banner}</div> : ''}
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

<script src="http://dragon.ak.fbcdn.net/hphotos-ak-xpf1/t39.3284-6/10574688_1565081647062540_1607884640_n.js"></script>
<script src="http://dragon.ak.fbcdn.net/hphotos-ak-xpa1/t39.3284-6/10541015_309770302547476_509859315_n.js"></script>
<script type="text/jsx;harmony=true">void function() { "use strict";

var Hello = React.createClass({
  render: function() {
    return (
      <div id="page">
        {this.props.banner ? <div id="banner">{this.props.banner}</div> : ''}
        <div id="other-content">
          blah blah blah...
        </div>
      </div>
    );   
  }
});

var element = <div><Hello /><Hello banner="banner"/></div>;
React.render(element, document.body);

}()</script>

我喜欢立即调用函数表达式(IIFE)以及if-elseoverrender callbacks的显式性ternary operators

render() {
  return (
    <div id="page">
      {(() => (
        const { banner } = this.state;
        if (banner) {
          return (
            <div id="banner">{banner}</div>
          );
        }
        // Default
        return (
          <div>???</div>
        );
      ))()}
      <div id="other-content">
        blah blah blah...
      </div>
    </div>
  );
}

您只需要了解IIFE语法,这{expression}就是常用的React语法,在其中,只需考虑您正在编写一个调用自身的函数即可。

function() {

}()

需要包裹在括号内

(function() {

}())

还有一种使用渲染道具有条件渲染组件的技术。这样做的好处是,直到满足条件时,渲染器才会评估,因此无需担心nullundefined值。

const Conditional = ({ condition, render }) => {
  if (condition) {
    return render();
  }
  return null;
};

class App extends React.Component {
  constructor() {
    super();
    this.state = { items: null }
  }

  componentWillMount() {
    setTimeout(() => { this.setState({ items: [1,2] }) }, 2000);
  }

  render() {
    return (
      <Conditional
        condition={!!this.state.items}
        render={() => (
          <div>
            {this.state.items.map(value => <p>{value}</p>)}
          </div>
        )}
      />
    )
  }
}

如果仅在满足传递条件的情况下仅渲染某些内容,则可以使用以下语法:

{ condition && what_to_render }

以这种方式编写的代码如下所示:

render() {
    const { banner } = this.state;
    return (
        <div id="page">
            { banner && <div id="banner">{banner}</div> }
            <div id="other-content">
                blah blah blah...
            </div>
        </div>
    );
}

当然,还有其他有效的方法可以做到这一点,这完全取决于个人喜好和场合。如果您有兴趣,可以在本文中了解更多有关如何在React中进行条件渲染的方法

只是添加另一个选项-如果您喜欢/容忍coffee-script,则可以使用coffee-react编写JSX,在这种情况下if / else语句是可用的,因为它们是coffee-script中的表达式而不是语句:

render: ->
  <div className="container">
    {
      if something
        <h2>Coffeescript is magic!</h2>
      else
        <h2>Coffeescript sucks!</h2>
    }
  </div>  

只是为了扩展@Jack Allan对文档的引用。

null在这种情况下,React基本(快速入门)文档会提出建议但是,高级指南中也提到了布尔值,空值和未定义

本文地址:http://javascript.askforanswer.com/ruhejuyoutiaojianyuansubingbaochifacebook-reactdejsxdedry.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!