模板条件渲染很常见,往往会随机使用其中一种方式使用,怎么写维护性更高呢?
-
IF/ELSE
-
JSX 支持 js 和 html 混写,交替使用可以解决条件渲染问题
-
function render() { if (renderComponentCondition1) { return <renderComponent1 /> } else { return <div /> } }
-
-
return
null
-
不想渲染空元素,最好使用
null
代替空的div
,能有效提升组件渲染效率 -
function render () { if (renderComponentCondition1) { return <renderComponent1 /> } else { return null } }
-
-
组件变量
-
组件赋值到变量上,这样可以在 return 前任意修改
-
function render () { let component = null if(renderComponentCondition1) { component = <Component1 /> } return component }
-
-
三元运算符
-
function render () { return renderComponentCondition ? <Component1 /> : null }
-
-
&& 断言符号
function render() { return renderComponentCondition && <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 组件
-
用一个条件渲染组件
IF
代替 js 函数的 if -
<If condition={true}> <span>Hi!</span> </If> // 实现 const If = (props) => { const condition = props.condition || false const positive = props.then || null const nagative = props.else || null return condition ? positive : nagative }
-
-
高阶组件
-
返回一个新组建的函数,并接受一个组件作为参数。在高阶组件里面写条件语句,返回不同的组件即可。
-
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 SubCompoent () { return isOk ? <Component1 /> : <Component2 /> }
-
函数拆分下虽然降低函数平均逻辑复杂度,但是提高了连接复杂度。
-
如果代码量比较小的时候,10 个函数做逻辑抽象拆分出十个子函数,逻辑复杂度不变,但是函数变多了。简单的十个函数,那很快就能改完,如果做了逻辑抽象, 可能拆分过多也会影响线索查找。不过总线索深度一般是固定在五层左右的。
-
如果理解 5 个或者 10 个函数成本都差不多,但是没有做逻辑抽象的时候,5 个函数各自参杂了其他的逻辑,反而会影响对函数的理解,也就是我们常说的
函数单一功能
-
组件封装需要适度,连接成本(也就是我们平时所说的组件通信,这种传值也是需要设计成本的,所以颗粒度的设计也需要认真思考)
-
- 合理的逻辑抽象有助于提高程序的抽象能力,作者更倾向于使用子函数、子组件、IF 组件、高阶组件做条件渲染。
- 抽象之后复用性更强,函数单一性逻辑更清晰,切面编程时能更快理解。
- 逻辑抽象需要考虑项目复杂度,避免过度抽象,破坏项目整体性。