React 高级指引

1、代码分隔

      大多数的React应用都会使用WebpackBrowserify这类的构建工具来打包文件。打包是一个将文件引入并合并

到一个单独文件的过程。接着在页面上引入该捆绑,整个应该即可一次性加载!

       代码分隔是由诸如Webpack(代码分隔)和诸如因字束缚(factor-bundle)这类打包器支持的一项技术,能够创建

多个包并在运行时动态加载;

       1.1)import-- 你在应用的引入中分隔代码的最佳方式是通过动态的import()语法;

        例如:import OtherComponent from './OtherComponent';

       注意:动态import()语法目前只是一个ECMAScript提案,而不是正式的语法标准;

       1.2) React.lazy ----能够让你想渲染常规组件一样处理动态引入;

        例如:const OtherComponent  = React.lazy(()=>import('./OtherComponent'));

        注意:React.lazy接受一个函数,这个函数需要动态调用import().它必须返回一个Promise,该Promise需要解决一个

 default export的React组件;

         如果MyComponent渲染完成后,所有OtherComponent的模块还没有被加载完成,我们可以使用加载指示器为此组件做

优雅降级。使用Suspense组件来解决;(你可以将Suspense组件置于懒加载组件之上的任何位置。你甚至可以用一个Suspense组件包裹多个懒加载组件。

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}

2、上下文
上下文提供了一个无需为每层组件手动添加道具,就能在组件树间进行数据传递的方法;
在一个典型的React应用中,数据是通过props属性自上而下(由父及子)进行传递的,但是这种做法对于
某些类型的属性而言是极其繁琐的(例如:地区偏好,UI主题),这些属性是应用中许多组件都需要的。Context
提供了一种在组件之间共享此类值的方式,而不必显示的通过组件树逐层传递道具;

     使用Context之前到考虑:Context 主要应用场景在于很多不同层级的组件需要访问同样的一些数据。请谨慎使用,因为会使得组件的复用性变差

      如果你只是想避免层层传递一些属性,组件组合有时候是一个比context更好的解决方案;

      2.2) 上下文的API

             2.2.1) React.createContext

                         const MyContext = React.createContext(defaultValue);----创建一个Context对象。当React 渲染一个这个Context对象的组件,这个组件

                         会从组件树中离自身最近的那个匹配Provider中读取到当前的context值;如果没有,defaultValue参数才会生效;

                        (注意:将undefined传递给Provider时,组件的defaultValue不会生效)

             2.2.2)Context.Provider

                          <MyContext.Provider value={/*某个值*/}>-</MyContext.Provider>----每个Context对象都会返回一个Provider React组件,它允许消费组件订阅context变化;

                          Provider接受一个value属性,传递给消费组件。一个Provider可以和多个消费组件有对应的关系。多个Provider也可以嵌套使用,

                          里层会覆盖外层的数据;

                          (当Provider的value值发生变化时,他内部所有消费组件都会重新渲染。Provider以及内部consumer组件都不受制于shouldComponentUpdate函数

                           因此当consumer组件在其祖先组件退出更新的情况下也能更新;)

             2.2.3)Class.contextType

                          

                           挂载在class上的contextType属性会被重赋值为一个由React.createContext()创建的Context对象;这能让你

                          使用this.context来消费最近Context上的值。你可以在任何生命周期中访问到它,包含render函数中;

                    (注意:你只通过该API订阅单一context.如果想要订阅多个,阅读使用多个Context篇章。如果你正在使用实验性的public class fields语法,可以

                     使用static这个类属性来初始化你的contextType)

                    

            2.2.4)Context.Consumer

                    <MyContext.Consumer>{value=>/*基于context值进行渲染*/}</MyContext.Consumer>

                    React组件也可以订阅到context变更,这能让你在函数式组件中完成订阅context;

                    (注意:这需要函数作为子元素,这个函数接收当前的context值,返回一个React节点。传递给函数的value值等同于

                    网上组件树离这个context最近的Provider提供的value值。如果没有对应Provider,value参数等同于传递给createContext()的defaultValue)


    3、错误边界

          错误边界产生背景:过去,组件内的JavaScript错误会导致React的内部状态被破坏,并且在下一次渲染时产生可能无法追踪的错误。这些错误基本上由较早的其他代码(非React组件)

     错误引起。但是React并没有提供一种在组件中优雅处理这些错误的方式;

            为了解决上述问题,React 16引入了一个新的概念-----错误边界;

           错误边界是一种React组件,这种组件可以捕获并打印发生在其子组件树任何位置的JavaScript错误,并且会渲染出备用UI,

            而不是渲染那些崩溃了的子组件。错误边界在渲染期间、生命周期方法和整个组件树的构造函数中捕获错误;

            (注意:错误边界无法捕获一下场景中产生的错误:

               1、事件处理

               2、异步代码(例如:setTimeout 或 requestAnimationFrame回调函数)

               3、服务端渲染

               4、它自身抛出来的错误(并非他的子组件)

             )

      注意:错误边界无法捕获事件处理器内部的错误。

      React不需要错误边界来从事件处理程序的错误中恢复。与Render方法和生命周期方法不同,事件处理器不会再渲染期间触发。因此,

      抛出异常,React仍然能够知道需要在屏幕上显示什么。如果你需要在事件处理器内部捕获错误,使用普通的JavaScript  try/catch


     4、Refs转发

        ref转发是一项将ref自动地通过组件传递到其一子组件的技巧。对于大多数应用中的组件来说,这通常不是必须的。但是对某些组件,

       尤其是可重用的组件库是很有用的。

          4.1)转发refs到DOM组件

                 

                    上述实例发生情况的逐步解释:

                    1、我们通过调用React.createRef创建一个React ref并将其赋值给ref变量;

                    2、我们通过指定ref为JSX属性,将其向下传递给<FancyButton ref={ref}>;

                    3、React传递ref给forwardRef内函数(props,ref)=>....作为其第二个参数;

                    4、我们向下转发该ref参数到<button ref={ref}>,将其指定为JSX属性;

                    5、当ref挂载完成,ref.current将指向<button>DOM节点;

                    (注意:第二个参数ref只能使用React.forwardRef定义组件时存在。常规函数或class组件不接收ref参数,props中也不存在ref.

                      Ref转发不仅限于DOM组件,也可以转发refs到class组件实例中)


        5、Fragments

            React中一个常见模式是一个组件返回多个元素。Fragments允许你将子列表分组,而无需向DOM添加额外节点;

               render(){

                      return (

                           <React.Fragment>

                                  <ChildA/>

                                  <ChildB/>

                                  <ChildC/>

                           </React.Fragment>

                       )

                }

           或者可以将上述的<React.Fragment>转换为<>(目前很多工具尚不支持),如果是一个集合映射到一个Fragments数组,则

           <React.Fragment key = {item.id} >


       6、高阶组件

             高阶组件(HOC)是React中用于重用组件逻辑的高级技术。HOC本身不是React API一部分。它们是React组成性质的一种模式。

            高阶组件是一个获取组件并返回新组建的函数;

           const EnhanceComponent = higherOrderComponent(WrapperComponent);

            组件将props转换为UI,而高阶组件将组件转换为另一个组件;

原文地址:https://www.cnblogs.com/sunqq/p/10757318.html