显示或隐藏元素

我第一次搞乱了React.js,无法通过点击事件find显示或隐藏页面内容的方法。 我没有加载任何其他库到页面,所以我正在寻找一些本地方式使用React库。 这是我迄今为止。 点击事件触发时,我想显示结果div。

var Search= React.createClass({ handleClick: function (event) { console.log(this.prop); }, render: function () { return ( <div className="date-range"> <input type="submit" value="Search" onClick={this.handleClick} /> </div> ); } }); var Results = React.createClass({ render: function () { return ( <div id="results" className="search-results"> Some Results </div> ); } }); React.renderComponent(<Search /> , document.body); 

关键是使用setState更新click处理程序中组件的状态。 当状态改变被应用时,再次用新状态调用render方法:

 var Search = React.createClass({ getInitialState: function() { return { showResults: false }; }, onClick: function() { this.setState({ showResults: true }); }, render: function() { return ( <div> <input type="submit" value="Search" onClick={this.onClick} /> { this.state.showResults ? <Results /> : null } </div> ); } }); var Results = React.createClass({ render: function() { return ( <div id="results" className="search-results"> Some Results </div> ); } }); ReactDOM.render(<Search />, document.getElementById('container')); 

http://jsfiddle.net/kb3gN/15084/

 <style type="text/css"> .hidden { display:none; } </style> 
 render: function() { return ( <div className={this.props.shouldHide ? 'hidden' : ''}> This will be hidden if you set <tt>props.shouldHide</tt> to something truthy. </div> ); } 

以下是三元运算符的替代语法:

 { this.state.showMyComponent ? <MyComponent /> : null } 

相当于:

 { this.state.showMyComponent && <MyComponent /> } 

精益为什么


另外还有可选的display: 'none';语法display: 'none';

 <MyComponent style={this.state.showMyComponent ? {} : { display: 'none' }} /> 

但是,如果您过度使用display: 'none' ,这会导致DOM污染,并最终减慢您的应用程序。

与最新的版本反应0.11你也可以只返回null没有内容呈现。

https://facebook.github.io/react/blog/2014/07/13/react-v0.11-rc1.html#rendering-to-null

这是我使用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/

最好只在需要的时候才渲染一些元素,而不是用display: none添加一些css类。 如果你设置了display: none – 元素仍然是通过反应渲染的,并且添加到DOM – 这会对性能造成不良影响。

想象一下,你有页面的标签,其中每个标签有很多的内容,只有一个标签一次打开。 在DOM只保留那些应该显示的元素会好得多。

在上面的代码中,为了实现这一点,我使用的代码如下:

 {opened && <SomeElement />} 

只有opened才会呈现SomeElement 。 这是因为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 

我创build了一个小组件来处理这个问题: https : //www.npmjs.com/package/react-toggle-display

它根据hideshow props将style属性设置为display: none !important

用法示例:

 var ToggleDisplay = require('react-toggle-display'); var Search = React.createClass({ getInitialState: function() { return { showResults: false }; }, onClick: function() { this.setState({ showResults: true }); }, render: function() { return ( <div> <input type="submit" value="Search" onClick={this.onClick} /> <ToggleDisplay show={this.state.showResults}> <Results /> </ToggleDisplay> </div> ); } }); var Results = React.createClass({ render: function() { return ( <div id="results" className="search-results"> Some Results </div> ); } }); React.renderComponent(<Search />, document.body); 

你在状态中设置一个布尔值(例如'show'),然后执行:

 var style = {}; if (!this.state.show) { style.display = 'none' } return <div style={style}>...</div> 

这是使用虚拟DOM的好方法:

阵营:

  var Comp = React.createClass({ getInitialState: function(){ return {hide: false}; }, toggle: function(){ this.setState({hide: !this.state.hide}); }, render: function() { return <div> <button onClick={this.toggle}>toggle</button> <div className={'hide-' + this.state.hide}>Hi there</div> </div>; } }); ReactDOM.render( <Comp />, document.getElementById('container') ); 

CSS

  .hide-true { display: none; } 

在这里拨弄

在某些情况下,高阶组件可能是有用的:

创build更高阶的组件:

 export var HidableComponent = (ComposedComponent) => class extends React.Component { render() { if ((this.props.shouldHide!=null && this.props.shouldHide()) || this.props.hidden) return null; return <ComposedComponent {...this.props} />; } }; 

扩展你自己的组件:

 export const MyComp= HidableComponent(MyCompBasic); 

那么你可以像这样使用它:

 <MyComp hidden={true} ... /> <MyComp shouldHide={this.props.useSomeFunctionHere} ... /> 

这减less了一些样板文件,并强制遵守命名约定,但请注意MyComp仍将被实例化 – 前面提到了省略的方法:

{ !hidden && <MyComp ... /> }

如果你想看看如何TOGGLE显示一个组件结帐这个小提琴。

http://jsfiddle.net/mnoster/kb3gN/16387/

 var Search = React.createClass({ getInitialState: function() { return { shouldHide:false }; }, onClick: function() { console.log("onclick"); if(!this.state.shouldHide){ this.setState({ shouldHide: true }) }else{ this.setState({ shouldHide: false }) } }, render: function() { return ( <div> <button onClick={this.onClick}>click me</button> <p className={this.state.shouldHide ? 'hidden' : ''} >yoyoyoyoyo</p> </div> ); } }); ReactDOM.render( <Search /> , document.getElementById('container')); 

根据文档,最佳实践如下:

  {this.state.showFooter && <Foorter />} 

只有当状态有效时才渲染元素。

我从React团队的这个陈述开始:

在React中,你可以创build不同的组件来封装你需要的行为。 然后,只能渲染其中的一部分,具体取决于应用程序的状态。

React中的条件呈现与JavaScript中的条件工作方式相同。 使用JavaScript运算符(如if或条件运算符)来创build表示当前状态的元素,并让React更新UI以匹配它们。

你基本上需要在button被点击的时候显示组件,你可以用两种方法,使用纯粹的React或使用CSS,使用纯粹的React方法,你可以在你的情况下做下面的代码,所以在第一次运行时,结果不显示为hideResultstrue ,但通过点击button,状态会改变, hideResultsfalse ,组件获取与新的价值条件再次呈现,这是非常常见的使用React中更改组件视图…

 var Search = React.createClass({ getInitialState: function() { return { hideResults: true }; }, handleClick: function() { this.setState({ hideResults: false }); }, render: function() { return ( <div> <input type="submit" value="Search" onClick={this.handleClick} /> { !this.state.hideResults && <Results /> } </div> ); } }); var Results = React.createClass({ render: function() { return ( <div id="results" className="search-results"> Some Results </div>); } }); ReactDOM.render(<Search />, document.body); 

如果你想在React的条件渲染中进一步学习,看看这里 。

已经有好几个很好的答案了,但是我不认为这些答案已经被很好地解释了,并且有几个方法包含了一些可能会让人们感到沮丧的问题。 所以我要通过三种主要方式(加上一个离题选项)来做到这一点,并解释利弊。 我主要是写这个,因为选项1被推荐了很多,如果使用不正确的话,这个选项有很多潜在的问题。

选项1:父项中的条件呈现。

我不喜欢这种方法,除非你只是一次渲染组件,并将其留在那里。 问题在于,每次切换可视性时,都会从头开始创build组件。 这里是例子。 LogoutButton或LoginButton被有条件地渲染到父LoginControl中。 如果你运行这个,你会注意到每个button点击构造函数都会被调用。 https://codepen.io/Kelnor/pen/LzPdpN?editors=1111

 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 = null; if (isLoggedIn) { button = <LogoutButton onClick={this.handleLogoutClick} />; } else { button = <LoginButton onClick={this.handleLoginClick} />; } return ( <div> <Greeting isLoggedIn={isLoggedIn} /> {button} </div> ); } } class LogoutButton extends React.Component{ constructor(props, context){ super(props, context) console.log('created logout button'); } render(){ return ( <button onClick={this.props.onClick}> Logout </button> ); } } class LoginButton extends React.Component{ constructor(props, context){ super(props, context) console.log('created login button'); } render(){ return ( <button onClick={this.props.onClick}> Login </button> ); } } function UserGreeting(props) { return <h1>Welcome back!</h1>; } function GuestGreeting(props) { return <h1>Please sign up.</h1>; } function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn) { return <UserGreeting />; } return <GuestGreeting />; } ReactDOM.render( <LoginControl />, document.getElementById('root') ); 

现在React从零开始创build组件很快。 但是,创build它时仍然需要调用你的代码。 所以,如果你的构造函数,componentDidMount,render等代码很昂贵,那么它会显着减慢显示组件。 这也意味着你不能在有状态的组件中使用这个组件,当你隐藏状态(并且在显示时恢复)时,状态组件将被保留。一个好处是隐藏组件不会被创build,直到它被选中。 所以隐藏的组件不会延迟您的初始页面加载。 在切换时,您可能还会遇到需要重置有状态组件的情况。 在这种情况下,这是你最好的select。

选项2:对孩子进行条件渲染

这创build了两个组件一次。 然后,如果组件被隐藏,则将其余的渲染代码短路。 您也可以使用可见的道具在其他方法中短路其他逻辑。 注意codepen页面中的console.log。 https://codepen.io/Kelnor/pen/YrKaWZ?editors=0011

 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; return ( <div> <Greeting isLoggedIn={isLoggedIn} /> <LoginButton isLoggedIn={isLoggedIn} onClick={this.handleLoginClick}/> <LogoutButton isLoggedIn={isLoggedIn} onClick={this.handleLogoutClick}/> </div> ); } } class LogoutButton extends React.Component{ constructor(props, context){ super(props, context) console.log('created logout button'); } render(){ if(!this.props.isLoggedIn){ return null; } return ( <button onClick={this.props.onClick}> Logout </button> ); } } class LoginButton extends React.Component{ constructor(props, context){ super(props, context) console.log('created login button'); } render(){ if(this.props.isLoggedIn){ return null; } return ( <button onClick={this.props.onClick}> Login </button> ); } } function UserGreeting(props) { return <h1>Welcome back!</h1>; } function GuestGreeting(props) { return <h1>Please sign up.</h1>; } function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn) { return <UserGreeting />; } return <GuestGreeting />; } ReactDOM.render( <LoginControl />, document.getElementById('root') ); 

现在,如果初始化逻辑很快,孩子们是无状态的,那么在性能或function上就不会有什么不同了。 但是,为什么React无论如何创build一个全新的组件? 如果初始化费用昂贵,则每次切换一个组件时,选项1都会运行,这会在切换时降低页面的速度。 选项2将在首页加载时运行所有组件的入口。 放慢第一个负载。 应该再次注意。 如果只是基于条件显示组件一次,而不是切换组件,或者希望在切换时重置该组件,则选项1很好,可能是最好的select。

如果缓慢的页面加载是一个问题,但是这意味着你在生命周期方法中有昂贵的代码,这通常不是一个好主意。 您可以并可能应该通过将昂贵的代码移出生命周期方法来解决缓慢的页面加载问题。 将它移动到由ComponentDidMount启动的asynchronous函数,并使用setState()将该callback放入状态variables中。 如果状态variables为空,并且组件可见,则渲染函数返回一个占位符。 否则,呈现数据。 这样,页面将加载迅速,填充选项卡。 您也可以将逻辑移动到父项中,并将结果作为道具推送给孩子。 这样你可以优先select哪个标签首先被加载。 或者caching结果,只在第一次显示组件时运行逻辑。

选项3:类隐藏

隐藏类可能是最容易实现的。 如前所述,您只需使用display:none创build一个CSS类,然后根据prop分配类。 缺点是调用每个隐藏组件的全部代码,并将所有隐藏的组件连接到DOM。 (选项1根本不会创build隐藏的组件,而选项2会在组件被隐藏时将不需要的代码短路,并且完全从DOM中删除组件。)看起来,根据评论者进行的一些testing,切换可见性的速度更快其他的答案,但我不能说这个。

选项4:一个组件,但改变道具。 或者也许根本没有组件,并cachingHTML。

这个不适用于每个应用程序,因为它不是关于隐藏组件,而是隐藏的话题,但对于某些用例而言,这可能是一个比隐藏更好的解决scheme。 假设你有标签。 编写一个React组件可能是可能的,只是使用道具来改变标签中显示的内容。 您还可以将JSX保存为状态variables,并使用prop来决定在渲染函数中返回哪个JSX。 如果必须生成JSX,那么执行它并将其caching在父级中,并将其作为道具发送。 或者在孩子身上产生并将其caching在孩子的状态中,并使用道具来select活动的孩子。