前言:前一篇記錄了【后台管理系統】目前進展開發中遇到的一些應用點,這一篇會梳理一些自己學習Ant Design Pro源碼的功能點。附:Ant Design Pro 在線預覽地址。
Dashboard指示板

pages/Dashboard 目錄下:Analysis.js分析頁、Monitor.js指控頁、WorkPlace.js工作台
用到的一些技術點:react v16.6 動態 import,React.lazy()、Suspense、Error boundaries (來源:Postbird博客)
Ⅰ、動態 import
在 Code-Splitting 部分,提出拆分組件的最佳方式(best way) 是使用動態的 import 方式。
比如下面兩種使用方式的對比:
之前:
import { add } from './math';
console.log(add(16, 26));
之后:
import("./math").then(math => {
console.log(math.add(16, 26));
});
可以發現動態 import 提供了 Promise 規范的 API,比如 .then(),關於 ES 動態 import,可以查看下面鏈接:
同樣,下面這篇文章上也可以參考:
目前動態 import 仍舊是 ECMAScript 的提案,並沒有納入規范,不過既然 react 能夠大力的推進,應該下個標准會被寫入。可以查看 TC39-https://github.com/tc39/proposal-dynamic-import
動態 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() 和 Suspense
1、React.lazy()
動態 import 主要應用場景是延遲加載方法,對於組件來說,並不是很適用,但是 React.lazy 對於組件的加載則是有比較大的幫助。
- 目前明確指出,React.lazy 和 suspense 並不適用於服務端渲染
先看一下前后的區別,
之前代碼:
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,也就是引入的內容,而前面引入的是個組件,因此會打印出如下信息:

2、Suspense
要使用 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 就沒意義,也沒效果了。
Ⅲ、Error boundaries
上面 Suspense 是對 loading 的一個打底,而錯誤邊界可以在任何一個組件中進行錯誤的捕獲。
這里只對錯誤邊界進行一個簡要的使用,具體的文檔見下:
這里的錯誤邊界用在這個位置是為了當組件懶加載失敗的時候,進行錯誤的捕獲和保護:
1、創建錯誤邊界組件
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;
}
}
2、在組件中使用錯誤邊界
將創建的錯誤邊界掛到組件中,不適用 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);
1、組件繼承自PureComponent
PureComponent 純組件是React新加的一個類,是優化 React 應用程序最重要的方法之一,易於實施。
只要把繼承類從 Component 換成 PureComponent 即可,可以減少不必要的 render 操作的次數,從而提高性能,而且可以少寫 shouldComponentUpdate 函數,節省了點代碼。
具體使用及原理可參看下面的鏈接:
2、設置多個PageHeader網格式分布樣式
.main {
width: 100%;
height: 100%;
min-height: 100%;
transition: 0.3s;
&.wide {
max-width: 1200px;
margin: 0 auto;
}
}
Ⅱ、Charts圖表
利用 Ant Design Pro 提供的圖表套件,可以靈活組合符合設計規范的圖表來滿足復雜的業務需求。
- 官網Charts組件介紹:https://pro.ant.design/components/Charts-cn/
![]() |
|
| 迷你區域圖MiniArea | 迷你進度條MiniProgress |
![]() |
![]() |
| 迷你柱狀圖MiniBar | 柱狀圖Bar |
![]() |
![]() |
| 餅狀圖Pie, yuan | 迷你餅狀圖Pie |





