Skip to content

Latest commit

 

History

History
232 lines (166 loc) · 5.43 KB

61.精读《React 八种条件渲染》.md

File metadata and controls

232 lines (166 loc) · 5.43 KB

61.精读《React 八种条件渲染》

模板条件渲染很常见,往往会随机使用其中一种方式使用,怎么写维护性更高呢?

概述

  • 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 个函数各自参杂了其他的逻辑,反而会影响对函数的理解,也就是我们常说的函数单一功能

    • 组件封装需要适度,连接成本(也就是我们平时所说的组件通信,这种传值也是需要设计成本的,所以颗粒度的设计也需要认真思考)

summary

  • 合理的逻辑抽象有助于提高程序的抽象能力,作者更倾向于使用子函数、子组件、IF 组件、高阶组件做条件渲染。
  • 抽象之后复用性更强,函数单一性逻辑更清晰,切面编程时能更快理解。
  • 逻辑抽象需要考虑项目复杂度,避免过度抽象,破坏项目整体性。