前言:前一篇记录了【后台管理系统】目前进展开发中遇到的一些应用点,这一篇会梳理一些本身学习Ant Design Pro源码的功能点。附:Ant Design Pro 在线预览地址。 javascript
pages/Dashboard 目录下:Analysis.js分析页、Monitor.js指控页、WorkPlace.js工做台css
用到的一些技术点:react v16.6 动态 import,React.lazy()、Suspense、Error boundaries (来源:Postbird博客)html
在 Code-Splitting 部分,提出拆分组件的最佳方式(best way) 是使用动态的 import 方式。java
好比下面两种使用方式的对比:react
以前:webpack
import { add } from './math'; console.log(add(16, 26));
以后: git
import("./math").then(math => { console.log(math.add(16, 26)); });
能够发现动态 import 提供了 Promise 规范的 API,好比 .then()
,关于 ES 动态 import,能够查看下面连接: github
一样,下面这篇文章上也能够参考:web
目前动态 import 仍旧是 ECMAScript 的提案,并无归入规范,不过既然 react 可以大力的推动,应该下个标准会被写入。能够查看 TC39-https://github.com/tc39/proposal-dynamic-importbabel
动态 import 主要用于延迟请求,对于组件我以为没什么太大的用处,可是对于延迟加载方法或者bundle很是有用,好比下面的代码:
能够发现,当触发点击事件的时候,才会去引入须要的方法或者是对象,而且因为 Promise API 的特性,可使用 Promise.all
Promise.race
这种 API,进行并行加载,而后在 then() 回调中调用方法,很是方便
class App extends Component { clickHandle = (e) => { Promise.all([ import('./mods/Lazy2') ]).then(([a]) => { console.log(a); a(e); }); } render() { return ( <div className="App"> <header className="App-header"> <button onClick={this.clickHandle}>click</button> </header> </div> ); } }
webpack 已经支持动态 import,在 create-react-app 和 next.js 中都已经可使用。若是是本身的 webpack 脚手架,须要在 webpack 中进行配置,具体的能够参考下面的方式https://webpack.js.org/guides/code-splitting/,最终配置完的样式相似于:https://gist.github.com/gaearon/ca6e803f5c604d37468b0091d9959269(这个连接是react文档给出的额,可是个人网络没法访问)
一样的,若是使用 babel,须要使用babel-plugin-syntax-dynamic-import这个组件来保证Babel不对动态导入进行转换。
React.lazy()
动态 import 主要应用场景是延迟加载方法,对于组件来讲,并非很适用,可是 React.lazy
对于组件的加载则是有比较大的帮助。
先看一下先后的区别,
以前代码:
import OtherComponent from './OtherComponent'; function MyComponent() { return ( <div> <OtherComponent /> </div> ); }
以后:
const OtherComponent = React.lazy(() => import('./OtherComponent')); function MyComponent() { return ( <div> <OtherComponent /> </div> ); }
关键点是 const OtherComponent = React.lazy(() => import('./OtherComponent'));
这个语句,摒弃了以前的 import X from 'x'
的静态引入方式。
一样的,这个变更会使得在组件渲染的时候,再去加载包含引入路径的组件。
React.lazy(()=>{})
这个方法的回调中其实就是包含了一个动态 import, 如下面方式举例:
const Lazy2 = React.lazy(() =>import('./mods/Lazy2').then((e) => { console.log(e); }));
箭头句柄后面就是一个动态 import 的使用, 打印出来的 e,也就是引入的内容,而前面引入的是个组件,所以会打印出以下信息:
要使用 Suspense
,须要从 react 中 import:
import React, { Component, Suspense } from 'react';
既然是延迟加载,就会有一个加载过程,以前在渲染的时候,咱们基本都是自顶一个一个 <Loading>
组件,而后经过变量控制进行操做,若是加载完成,则取消掉 <Loading>
组件。
若是直接使用 React.lazy
,会报错误:须要一个 placeholder ui
既然是延迟加载,就必定会有一个loading的过程,而 Suspense
正是完成这个过程。
如同上面的效果会有一个动态的过程,代码以下:
render() { return ( <div className="App"> <header className="App-header"> <Suspense fallback={<div>Loading...</div>}> {this.renderList()} </Suspense> </header> </div> ); }
Suspense
使用的时候,fallback
必定是存在且有内容的, 不然会报错。
针对网络请求的 loading,我并没觉的这种 fallback 有什么帮助,由于他是组件加载的 loading,若是组件加载完了,那么再去 fallback 就没意义,也没效果了。
上面 Suspense
是对 loading 的一个打底,而错误边界能够在任何一个组件中进行错误的捕获。
这里只对错误边界进行一个简要的使用,具体的文档见下:
这里的错误边界用在这个位置是为了当组件懒加载失败的时候,进行错误的捕获和保护:
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } // 从error中接收错误并设置 state static getDerivedStateFromError(error) { // Update state so the next render will show the fallback UI. return { hasError: true }; } componentDidCatch(error, info) { // You can also log the error to an error reporting service logErrorToMyService(error, info); } render() { if (this.state.hasError) { // You can render any custom fallback UI return <h1>Something went wrong.</h1>; } return this.props.children; } }
将建立的错误边界挂到组件中,不适用 React.lazy
,由于已经没有更上一层次的错误组件了,万一错误边界组件也懒加载出错,会致使没法捕获。
错误边界组件中,经过 componentDidCatch
捕获错误,能够设置信息或发错误日志。
错误边界的使用示例能够参考下面的示例:
按照上面的例子,在使用的时候,组件中报错,触发错误边界:
Lazy2.jsx:
render() { throw new Error('I crashed!'); return ( <div> <p>{this.state.title}</p> </div> ); }
App.jsx:
<Error> {this.renderList()} </Error>
Error.jsx:
import React, {Component} from 'react'; class Error extends Component { constructor(props) { super(props); this.state = { error: null, errorInfo: null }; } componentDidCatch(error, errorInfo) { // Catch errors in any components below and re-render with error message this.setState({ error: error, errorInfo: errorInfo }) // You can also log error messages to an error reporting service here } render() { if (this.state.errorInfo) { // Error path return ( <div> <h2>Something went wrong.</h2> <details style={{ whiteSpace: 'pre-wrap' }}> {this.state.error && this.state.error.toString()} <br /> {this.state.errorInfo.componentStack} </details> </div> ); } // Normally, just render children return this.props.children; } } export default Error;
最终结果:
Dashboard模块除了上面的新技术点,在AntD组件和布局上也有一些经常使用的知识点:GridContent网格内容布局、Charts图表、Tabs标签页
Ⅰ、GridContent网格内容布局
使用GridContent组件,须要从components/PageHeaderWrapper目录下引用,源码以下↓
import React, { PureComponent } from 'react'; import { connect } from 'dva'; import styles from './GridContent.less'; class GridContent extends PureComponent { render() { const { contentWidth, children } = this.props; let className = `${styles.main}`; if (contentWidth === 'Fixed') { className = `${styles.main} ${styles.wide}`; } return <div className={className}>{children}</div>; } } export default connect(({ setting }) => ({ contentWidth: setting.contentWidth, }))(GridContent);
PureComponent 纯组件是React新加的一个类,是优化 React
应用程序最重要的方法之一,易于实施。
只要把继承类从 Component
换成 PureComponent
便可,能够减小没必要要的 render
操做的次数,从而提升性能,并且能够少写 shouldComponentUpdate
函数,节省了点代码。
具体使用及原理可参看下面的连接:
.main { width: 100%; height: 100%; min-height: 100%; transition: 0.3s; &.wide { max-width: 1200px; margin: 0 auto; } }
利用 Ant Design Pro 提供的图表套件,能够灵活组合符合设计规范的图表来知足复杂的业务需求。
![]() |
![]() |
迷你区域图MiniArea | 迷你进度条MiniProgress |
![]() |
![]() |
迷你柱状图MiniBar | 柱状图Bar |
![]() |
![]() |
饼状图Pie, yuan | 迷你饼状图Pie |