条件渲染
引言
我们知道react是用于构建用户界面的JavaScript库。可以用其创建拥有各自状态的组件,在由这些组件构建更加复杂的UI组件。但是在某些情况下,我们需要根据不同的
条件渲染不同的UI,实现不同的功能。react是用JSX来定义UI组件的,但是它不直接支持循环或条件表达式,即使这样,我们也可以用条件渲染来解决我们的遇到的问题。
在react中条件渲染方法
- if...else
- 使用null阻止渲染
- 元素变量
- 与运算符&&
- 三元运算符
- 立即调用的函数表达式(IIFE)
- 子组件
- 高阶成分(HOC)
if...else
function UserGreeting(props){
return <h1>Welcome back!</h1>
}
function GusetGreeting(props){
return <h1>Please sign up.</h1>
}
function Greeting(props){
const isLoggedIn = props.isLoggedIn;
if(isLoggedIn){
return <UserGreeting />;
}
return <GusetGreeting />;
}
ReactDOM.render(
<Greeting isLoggedIn={true} />,
document.getElementById('condition')
)
上面的代码中,会根据用户是否登录来决定显示上面哪一个组件
使用null阻止渲染
在极少数情况下,你可能希望能隐藏组件,即使他已经被其他组件渲染。若要完成此操作,可以让
render方法直接返回null,而不进行任何渲染
下面示例中,<WarningBanner />
会根据prop中warn
的值来进行渲染,如果warn
的值是false
,那么组件则不会渲染
function WarningBanner(props){
if(!props.warn){
return null
}
return (
<div className="warning">warning!</div>
)
}
class Page extends React.Component{
constructor(props){
super(props);
this.state = {
showWarning:true
};
this.handleToggleClick = this.handleToggleClick.bind(this);
}
handleToggleClick(){
this.setState(state => ({
showWarning:!state.showWarning
}))
}
render(){
return(
<div>
<WarningBanner warn={this.state.showWarning} />
<button onClick={this.handleToggleClick}>
{
this.state.showWarning?'Hide':'Show'
}
</button>
</div>
)
}
}
ReactDOM.render(<Page />,document.getElementById('warning'))
元素变量
你可以使用变量来储存元素,他可以帮助你有条件地渲染组件一部分,而其他的渲染部分并不会因此而改变
下面例子中,我们创建了两个函数组件,分别代表了登录和登出按钮,同事创建一个名为LoginControl
的又状态的组件,它将会根据当前的状态来渲染<LoginButton />
或者<LogoutButton>
。同时它还会
渲染上一个示例中的<Greeting />
function LoginButton(props){
return (
<button onClick={props.onClick}>Login</button>
)
}
function LogoutButton(props){
return(
<button onClick={props.onClick}>logout</button>
)
}
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;
if(isLoggedIn){
button = <LogoutButton onClick = {this.handleLogoutClick} />
}else{
button = <LoginButton onClick ={this.handleLoginClick} />
}
return(
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
)
}
}
ReactDOM.render(<LoginControl />,document.getElementById('login-btn'))
与运算符&&
通过花括号包裹代码,你可以在JSX中嵌入任何表达式。这也包括JavaScript中的逻辑与(&&)
运算符。他可以很方便地进行元素的条件渲染。
function Mailbox(props){
const unreadMessages = props.unreadMessages;
return(
<div>
<h1>Hello!</h1>
{
unreadMessages.length>0&&
<h2>you have {unreadMessages.length}unread messages</h2>
}
</div>
)
}
const messages = ['React','Re:React','Re:Re:React'];
ReactDOM.render(
<Mailbox unreadMessages={messages} />,
document.getElementById('mail-box')
)
之所以能这样做,是因为在JavaScript中,true&&expression
总是会返回expression
而false&&expression
总是会返回false
。
因此,如果条件是true
,&&
右侧的元素就会被渲染,如果是false
,React会忽略并跳过它。
三元运算符
另一种内联条件渲染的方法是使用JavaScript中的三目运算符condition?true:false
将<LoginControl />
组件中的render改为如下
render(){
const isLoggedIn = this.state.isLoggedIn;
return(
<div>
<Greeting isLoggedIn={isLoggedIn} />
{isLoggedIn?<LogoutButton onClick = {this.handleLogoutClick} />:<LoginButton onClick ={this.handleLoginClick} />}
</div>
)
}
立即调用的函数表达式(IIFE)
立即执行函数如下面代码所示
(function myFunction(/*arguments*/){})(/*arguments*/)
当深陷JSX代码中,又想写一大块逻辑时,除了回到上方,还可以使用IIFE:
function render(){
return(
<div>
{
(() =>{
if(renderComponent1){
return <Component1 />
}else{
return <div />
}
})()
}
</div>
)
}
子组件
这是IIFE的变种,也就是把这段位立即执行函数替换成一个普通函数:
function render(){
return(
<div>
<SubRender />
</div>
)
}
function SubRender(){
if(renderComponent1){
return <Component1 />
}else{
return <div />
}
}
高阶组件
高阶组件,就是返回一个新组件的函数,并且接收一个组件作为参数。
那么我们就能在高阶组件里写条件语句,返回不同的组件即可
function highrOrderComponent(component){
return function EnhancedComponent(props){
if(condition){
return <AnotherComponent {...props} />
}
return <Component {...props} />
}
}