我第一次搞乱React.js,无法通过点击事件找到在页面上显示或隐藏某些内容的方法.我没有加载任何其他库到页面,所以我正在寻找一些使用React库的本地方式.这就是我到目前为止所拥有的.我想在点击事件触发时显示结果div.
var Search= React.createClass({
handleClick: function (event) {
console.log(this.prop);
},
render: function () {
return (
);
}
});
var Results = React.createClass({
render: function () {
return (
Some Results
);
}
});
React.renderComponent( , document.body);
Douglas.. 480
关键是使用单击处理程序更新组件的状态setState
.当应用状态更改时,将render
使用新状态再次调用该方法:
var Search = React.createClass({
getInitialState: function() {
return { showResults: false };
},
onClick: function() {
this.setState({ showResults: true });
},
render: function() {
return (
{ this.state.showResults ? : null }
);
}
});
var Results = React.createClass({
render: function() {
return (
Some Results
);
}
});
ReactDOM.render( , document.getElementById('container'));
http://jsfiddle.net/kb3gN/15084/
关键是使用单击处理程序更新组件的状态setState
.当应用状态更改时,将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/
以下是三元运算符的替代语法:
{ this.state.showMyComponent ? <MyComponent /> : null }
相当于:
{ this.state.showMyComponent && <MyComponent /> }
精益为什么
也是替代语法 display: 'none';
<MyComponent none' }} />
但是,如果过度使用display: 'none'
,会导致DOM污染并最终减慢您的应用程序.
使用最新版本反应0.11,您也可以返回null以不呈现任何内容.
https://facebook.github.io/react/blog/2014/07/13/react-v0.11-rc1.html#rendering-to-null
<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>
);
}
// or in more modern JS and stateless react
const Example = props => <div className={props.shouldHide}/>Hello</div>
已经有几个很好的答案,但我认为它们没有被很好地解释,并且给出的一些方法包含一些可能会让人感到惊讶的问题.因此,我将讨论三种主要方式(加上一个非主题选项),并解释其优缺点.我主要是写这个,因为选项1被推荐了很多,如果没有正确使用,那么该选项存在很多潜在的问题.
我不喜欢这种方法,除非你只是将组件渲染一次并留在那里.问题是,每次切换可见性时,它都会导致从头开始创建组件的反应.这是一个例子.LogoutButton或LoginButton在父LoginControl中有条件地呈现.如果你运行它,你会注意到每次按下按钮时都会调用构造函数.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从头开始创建组件非常快.但是,它仍然必须在创建时调用您的代码.因此,如果您的构造函数,componentDidMount,render等代码很昂贵,那么它将显着减慢显示组件的速度.这也意味着你不能在有状态的组件中使用它,你希望隐藏状态时保存状态(并在显示时恢复).一个优点是隐藏的组件在被选中之前根本不会被创建.因此隐藏的组件不会延迟您的初始页面加载.在切换时,可能还有一些情况需要重置有状态组件.在这种情况下,这是您的最佳选择.
这会创建两个组件一次.如果隐藏组件,则将其余的渲染代码短路.您还可以使用可见道具在其他方法中将其他逻辑短路.注意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') );
现在,如果初始化逻辑很快并且子项是无状态的,那么您将看不到性能或功能上的差异.但是,为什么React会在每次切换时创建一个全新的组件?但是,如果初始化很昂贵,那么每次切换组件时选项1都会运行它,这会在切换时减慢页面速度.选项2将在首页加载时运行所有组件的内容.放慢第一次加载.应该再说一遍.如果您只是根据条件显示组件一次并且没有切换它,或者您希望它在切换时重置,那么选项1很好,可能是最好的选择.
如果慢页面加载是一个问题,那么这意味着你在生命周期方法中得到了昂贵的代码,这通常不是一个好主意.您可以并且可能应该通过将昂贵的代码移出生命周期方法来解决缓慢的页面加载问题.将其移动到由ComponentDidMount启动的异步函数,并使回调将其置于具有setState()的状态变量中.如果state变量为null并且组件可见,则让render函数返回占位符.否则渲染数据.这样,页面将快速加载并在加载时填充选项卡.您还可以将逻辑移动到父级中,并将结果作为道具推送给子级.这样,您可以优先考虑首先加载哪些选项卡.或者缓存结果,并且仅在第一次显示组件时运行逻辑.
类隐藏可能是最容易实现的.如上所述,您只需使用display:none创建一个CSS类,并根据prop分配类.缺点是调用每个隐藏组件的整个代码,并将所有隐藏组件附加到DOM.(选项1根本不会创建隐藏的组件.当组件被隐藏时,选项2会短路不必要的代码并完全从DOM中删除组件.)根据评论者的一些测试,这似乎更快地切换可见性.其他答案,但我不能说.
这个不适用于每个应用程序,它不是主题,因为它不是隐藏组件,但它可能是一些用例比隐藏更好的解决方案.假设你有标签.可以编写一个React Component并只使用props来更改选项卡中显示的内容.您还可以将JSX保存到状态变量并使用prop来决定在render函数中返回哪个JSX.如果必须生成JSX,那么执行它并将其缓存在父级中,并将正确的一个作为prop发送.或者在子进程中生成并将其缓存在子进程中并使用props来选择活动状态.
这是我使用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 isOpened: false, }; // http://egorsmirnov.me/2015/08/16/react-and-es6-part3.html this.toggleBox = this.toggleBox.bind(this); } toggleBox() { this.setState(oldState => ({ isOpened: !oldState.isOpened })); } render() { const { title, children } = this.props; const { isOpened } = this.state; return ( <div className="box"> <div className="boxTitle" onClick={this.toggleBox}> {title} </div> {isOpened && children && ( <div className="boxContent"> {children} </div> )} </div> ); } } ReactDOM.render(( <ToggleBox title="Click me"> <div>Some content</div> </ToggleBox> ), document.getElementById('app'));
演示:http://jsfiddle.net/kb3gN/16688/
最好只在需要时渲染一些元素,而不是添加一些css类display: none
.如果你设置display: none
- 仍然通过反应生成元素并添加到DOM
- 这可能会对性能产生不良影响.
想象一下,您有包含选项卡的页面,其中每个选项卡都包含大量内容,并且一次只打开一个选项卡.DOM
只保留那些应该显示的元素要好得多.
在上面的代码中,为了实现这一点,我使用的代码如下:
{opened && <SomeElement />}
SomeElement
只有在opened
真实的情况下才会呈现.它的工作原理是因为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
我创建了一个小组件来为您处理:https://www.npmjs.com/package/react-toggle-display
它将style属性设置为display: none !important
基于hide
或show
props.
用法示例:
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>
根据文档,最佳做法如下:
{this.state.showFooter && <Footer />}
仅在状态有效时才渲染元素。
这是使用虚拟DOM的好方法:
阵营:
class Toggle extends React.Component { state = { show: true, } toggle = () => this.setState((currentState) => ({show: !currentState.show})); render() { return ( <div> <button onClick={this.toggle}> toggle: {this.state.show ? 'show' : 'hide'} </button> {this.state.show && <div>Hi there</div>} </div> ); } }
CSS
const Toggle = () => { const [show, toggleShow] = React.useState(true); return ( <div> <button onClick={() => toggleShow(!show)} > toggle: {show ? 'show' : 'hide'} </button> {show && <div>Hi there</div>} </div> ) }
在这里小提琴