二、React进阶

一、代码分割

为什么要使用代码分割:在用webpack进行打包的时候,每个模块被导入合并在一个文件,这个文件叫做 bundle,这些 bundle 在一张页面上包括了整个APP。然而,当 APP 增长的时候,这些 bundle 尺寸开始变得越来越大,因此影响了页面加载时间

使用ant design pro的时候,打包出来的不是一个bundle文件,而是把每个模块打包成了一个async.js。如果用了代码拆分中的import(),就会把对应的js模块单独进行打包,打包出来的js模块名字实例如56.ffeb4024.async.js如果不用这个import(),是不会打包出这个模块的

代码拆分简单说就是动态加载组件

// 这里,OtherComponent 是不会请求直到MyComponent开始渲染。但是,因为我们静态导入了 OtherComponent,它会和 MyComponent 一起打包
import OtherComponent from './OtherComponent';
export defautl function MyComponent() {
  return (
    <div>
      <h1>My Component</h1>
      <OtherComponent />
    </div>
  )
}。
1、import()语法进行代码分割
  • 这个就是webpack的import()函数(还不是 JavaScript 语言标准的一部分,但是一个期望不久被接受的提案)。import()的语法十分简单。该函数只接受一个参数,就是引用包的地址,这个地址与es6的import以及CommonJS的require语法用到的地址完全一致。返回值为一个promise,在这个promise里面就可以访问对应的包了
  • 在代码中所有被import()的模块,都将打成一个单独的包,放在chunk存储的目录下。
  • 感觉这个只适用于加载的包只在一个地方使用的情况,因为只有在then的回调里面才可以访问对应的组件,所以不怎么实用。用这个import可以使浏览器运行到这一行代码的时候,才去加载对应的资源
  • 在antd design pro的.umi文件夹里面,就已经是用这个代码分割,来定义了路由的了,所以打包出来不是只有单个的chunk
// 下面import在打包的时候,会打包出来多个chunk
import(/* webpackChunkName: "moment" */ 'moment')
.then(({default: moment}) => {
  const tommorrow =moment().startOf('day').add(1, 'day');
  return tomorrow.format('LLL');
})
// 下面为umi中的使用。实现路由的懒加载
import { routerRedux, dynamic as _dvaDynamic } from 'dva';
const routes = [{
    path: '/user',
    component: __IS_BROWSER
      ? _dvaDynamic({
          component: () =>
            import(/* webpackChunkName: "layouts__UserLayout" */ '../../layouts/UserLayout'), // 这里就使用了import()语法
          LoadingComponent: require('F:/demo/ant design pro demo/src/components/PageLoading/index')
            .default,
        })
      : require('../../layouts/UserLayout').default,
}]
2、React.lazy()函数和React.Suspense 组件

这两个东西是配合使用的。

  • React.lazy() 函数接收一个函数,函数的返回值必须为一个代表react组件的promise。所以就刚好配合上面的import()一起用了,也可以说是对import()这种动态导入方式的优化
    • 被React.lazy()函数包裹的组件,在没有被使用的时候不会被打包进chunk,而是在被调用的时候才被打包
    • React.lazy()现在只支持默认导出
  • <React.Suspense>组件,这个组件里面包裹的是React.lazy()函数返回的promise组件。一个Suspense可以包裹很多的lazy组件
    • fallback属性:这个属性表示,当React.lazy()函数返回的promise组件的状态为pending的时候出现在页面上的占位符,当状态为resolve的时候,这个占位符会消失。
import React, { Suspense, lazy } from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}> // 当里面的组件的状态为pending的时候,页面显示<div>Loading...</div>
        <section>
          <OtherComponent />
          <AnotherComponent />
        </section>
      </Suspense>
    </div>
  );
}

二、Context

Context:Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。相当于提供了在所有子组件,或者孙子组件都可以获取的一个全局数据

缺点是,用了context之后,会使子组件的可复用性变差

下面说的都是在class组件中使用,如果想在函数组件中使用,则需要使用hook

1、React.createContext()函数

简单说这个函数就是用来创建context的。返回一个Context对象,这个对象里面包含Provider组件和一个Consumer组件。可以给 React.createContext() 传入参数,代表Provider组件的value的默认值,不过没什么必要

2、Provider组件

这个组件是用React.createContext()函数创建的context对象里面的。Provider组件用在父组件中,有一个value属性,代表需要在所有子组件间共享的值。用来包装子组件,被包裹的所有子组件,都可以通过Consumer组件或者contextType属性来获取到Provider组件上面的value属性值

3、Consumer组件

Consumer组件用在子组件中,里面的值为一个函数,函数的参数就是provider里面的value。但是,这个Consumer组件不是很好用,一般不用。

4、使用contextType属性替代Consumer组件
  • contextType属性: 这个是在子组件中使用,用来替代Consumer组件,即可以不用Consumer组件来获取Provider组件上面的value值。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值