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


前言:前一篇記錄了【后台管理系統】目前進展開發中遇到的一些應用點,這一篇會梳理一些自己學習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 提供的圖表套件,可以靈活組合符合設計規范的圖表來滿足復雜的業務需求。

迷你區域圖MiniArea 迷你進度條MiniProgress
迷你柱狀圖MiniBar 柱狀圖Bar
餅狀圖Pie, yuan 迷你餅狀圖Pie


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM