本期精读的文章是:8 React conditional rendering methodshtml
介绍了八种 React 条件渲染方式。react
模版条件渲染很是常见,遇到的时候每每会随机选择一种方式使用,那么怎么写会有较好的维护性呢?先一块儿了解下有哪八种条件渲染方式吧!git
既然 JSX 支持 js 与 html 混写,那么交替使用就能解决条件渲染的问题:程序员
function render() { if (renderComponent1) { return <Component1 />; } else { return <div />; } }
null
若是不想渲染空元素,最好使用 null
代替空的 div
:github
function render() { if (renderComponent1) { return <Component1 />; } else { return null; } }
这样对 React 渲染效率有提高。typescript
将组件赋值到变量,就能够在 return 前任意修改它了。编程
function render() { let component = null; if (renderComponent1) { component = <Component1 />; } return component; }
三元运算符的语法以下:函数
condition ? expr_if_true : expr_if_false
用在 JSX 上也很方便:spa
function render() { return renderComponent1 ? <Component1 /> : null; }
但三元运算符产生嵌套时,理解成本会变得很高。code
这个是最经常使用了,由于代码量最少。
function render() { return renderComponent1 && <Component1 />; }
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 />; } }
作一个条件渲染组件 IF
代替 js 函数的 if
:
<If condition={true}> <span>Hi!</span> </If>
这个组件实现也很简单
const If = props => { const condition = props.condition || false; const positive = props.then || null; const negative = props.else || null; return condition ? positive : negative; };
高阶组件,就是返回一个新组件的函数,而且接收一个组件做为参数。
那么咱们就能在高阶组件里写条件语句,返回不一样的组件便可:
function higherOrderComponent(Component) { return function EnhancedComponent(props) { if (condition) { return <AnotherComponent {...props} />; } return <Component {...props} />; }; }
这么多方法都能实现条件渲染,那么重点在于可读性与可维护性。
好比经过调用函数实现组件渲染:
<div>{renderButton()}</div>
看上去仍是比较冗余,若是使用 renderButton
getter 定义,咱们就能够这么写它:
<div>{button}</div>
其实咱们想要的就是 button,而不是 renderButton
。那么还能够进一步,干脆封装成 JSX 组件:
<div> <Button /> </div>
是否要付出这些努力,取决于应用的复杂度。若是应用复杂度很是高,那你应当尽可能使用最后一种封装,让每一个文件的逻辑尽可能独立、简单。
若是应用复杂度比较低,那么注意不要过分封装,以避免把本身绕进去。
因此看来这又是一个没有固定答案的问题,选择何种方式封装,取决于应用复杂度。
对任何代码封装,都会增长这段 链接逻辑 的复杂度。
假定不管如何代码的复杂度都是恒定不变的,下面这段代码,链接复杂度为 0,而对于 render
函数而言,逻辑复杂度是 100:
function render() { if (renderComponent) { return isOk ? <Component1 /> : <Component2 />; } else { return <div />; } }
下面这段代码拆成了两个函数,逻辑复杂度对 render
SubComponent
来讲都是 50,但链接复杂度是 50:
function render() { if (renderComponent) { return <SubComponent>; } else { return <div />; } } function SubComponent() { return isOk ? <Component1 /> : <Component2 /> }
能够看到,咱们经过函数拆分,下降了每一个函数的逻辑复杂度,但却提升了链接复杂度。
下面来作一个比较,咱们假设一个正常的程序员,能够一次性轻松记忆 10 个函数。若是再多,函数之间的调用关系就会让人摸不着头脑。
在应用代码量比较小时,假设一共有 10 个函数,若是作了逻辑抽象,拆分出了 10 个子函数,那么总逻辑复杂度不变,函数变成了 20 个。
此时小王要修改此项目,他须要找到关键代码的位置。
若是没有作逻辑抽象,小王一会儿就记住了 10 个函数,而且很快完成了需求。
若是应用作了逻辑抽象,他须要理解的逻辑复杂度是不变的,可是要读的函数变成了 20 个。小王须要像侦探同样在线索中不断跳转,他仍是只找了 10 个关键函数,但一共也就 20 个函数,逻辑并不复杂,这值得吗?
小王内心可能会嘀咕:简单的逻辑瞎抽象,害我文件找了半天!
此时应用代码量比较大,假设一共有 500 个函数,咱们不考虑抽象后带来的复用好处,假设都没法复用,那么作了逻辑抽象后,那么总逻辑复杂度不变,函数变成了 1000 个。
此时小王接到了需求,终于维护了一个大项目。
小王知道这个项目很复杂,从一开始就没以为能理解项目全貌,因此把本身看成一名侦探,准备一步步探索。
如今有两种选择,一种是在未作逻辑抽象时探索,一种是在作过逻辑抽象后探索。
若是没作逻辑抽象,小王须要面对 500
个这种函数:
function render() { if (renderComponent) { return isOk ? <Component1 /> : <Component2 />; } else { return isReady ? <Component3 /> : <Component4 />; } }
若是作了逻辑抽象,小王须要面对 1000
个这种函数:
function render() { if (renderComponent) { return <Component1And2 />; } else { return <Component3And4 />; } }
在项目庞大后,总函数数量并不会影响对线索的查找,而总线索深度也几乎老是固定的,通常在 5 层左右。
小王理解 5 个或 10 个函数成本都差很少,但没有作逻辑抽象时,这 5 个函数各自参杂了其余逻辑,反而影响对函数的理解。
这时作逻辑抽象是合适的。
因此总的来讲,笔者更倾向使用子函数、子组件、IF 组件、高阶组件作条件渲染,由于这四种方式都能提升程序的抽象能力。
每每抽象后的代码会更具备复用性,单个函数逻辑更清晰,在切面编程时更利于理解。
当项目很简单时,整个项目的理解成本都很低,抽象带来的复杂度反而让项目变成了须要切面编程的时候,就得不偿失了。
总结一下:
&&
或者三元运算符、IIFE 等直接实现条件渲染。讨论地址是: 精读《React 八种条件渲染》 · Issue #90 · dt-fe/weekly
若是你想参与讨论,请点击这里,每周都有新的主题,周末或周一发布。