【後臺管理系統】—— Ant Design Pro入門學習&項目實踐筆記(三)

前言:前一篇記錄了【後臺管理系統】目前進展開發中遇到的一些應用點,這一篇會梳理一些本身學習Ant Design Pro源碼的功能點。附:Ant Design Pro 在線預覽地址。 javascript


Dashboard指示板

pages/Dashboard 目錄下:Analysis.js分析頁、Monitor.js指控頁、WorkPlace.js工做臺css

用到的一些技術點:react v16.6 動態 import,React.lazy()、Suspense、Error boundaries (來源:Postbird博客html

 

Ⅰ、動態 import

在 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() 和 Suspense

一、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,也就是引入的內容,而前面引入的是個組件,所以會打印出以下信息:  

二、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 的一個打底,而錯誤邊界能夠在任何一個組件中進行錯誤的捕獲。 

這裏只對錯誤邊界進行一個簡要的使用,具體的文檔見下: 

這裏的錯誤邊界用在這個位置是爲了當組件懶加載失敗的時候,進行錯誤的捕獲和保護 

一、建立錯誤邊界組件

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

PureComponent 純組件是React新加的一個類,是優化 React 應用程序最重要的方法之一,易於實施。

只要把繼承類從 Component 換成 PureComponent 便可,能夠減小沒必要要的 render 操做的次數,從而提升性能,並且能夠少寫 shouldComponentUpdate 函數,節省了點代碼。  

具體使用及原理可參看下面的連接:

二、設置多個PageHeader網格式分佈樣式

.main {
  width: 100%;
  height: 100%;
  min-height: 100%;
  transition: 0.3s;
  &.wide {
    max-width: 1200px;
    margin: 0 auto;
  }
}

 

Ⅱ、Charts圖表  

 利用 Ant Design Pro 提供的圖表套件,能夠靈活組合符合設計規範的圖表來知足複雜的業務需求。

迷你區域圖MiniArea 迷你進度條MiniProgress
迷你柱狀圖MiniBar 柱狀圖Bar
餅狀圖Pie, yuan 迷你餅狀圖Pie
相關文章
相關標籤/搜索