天天看點

React Lazy 和 Suspense

文章目錄

    • React.lazy 定義
      • 代碼分割
      • import 函數
      • import 函數示例
    • React.lazy 使用
      • Suspense

React.lazy 定義

  • React.lazy

    函數能讓你像渲染正常元件一樣處理動态引用的元件
  • 什麼意思呢,其實就是懶加載。其原理就是利用

    ES6 import()

    函數。這個

    import

    不是

    import

    指令。
  • 同樣是引人子產品,

    import

    指令是同步引人子產品,而

    import ()

    函數動态引入

代碼分割

  • 當Webpack 解析到該文法時,它會自動地開始進行代碼分割,分割成一個檔案,當使用到這個檔案的時候才會被異步加載
  • 當你的程式越來越大,代碼量越來越多。一個頁面上堆積了很多功能,也許有些功能很有可能都用不到,但是一樣下載下傳到頁面上,是以這裡面肯定有優化空間。比如圖檔懶加載

import 函數

  • math.js

    檔案
const add = (x, y) => {
    return x + y;
}
export default add;
           
//import 指令
import { add } from './math';

console.log(add(16, 26));

//import函數
import("./math").then(math => {
  console.log(math.add(16, 26));
});
           
動态

import()

文法目前隻是一個 ECMAScript (JavaScript) 提案, 而不是正式的文法标準。預計在不遠的将來就會被正式接受

import 函數示例

  • test.html

    代碼如下:
<div id="root">
  頁面無内容
</div>
<button id="btn">加載js</button>

<script>
  document.getElementById('btn').onclick=function(){
    import('./test.js').then(d=>{
      d.test()
    })
  }
</script>
           
  • test.js

    代碼如下:
function test(){
  document.getElementById('root')
  root.innerHTML='頁面變的有内容了'
}
export {test}
           
React Lazy 和 Suspense
  • 這時候打開web服務讓頁面以http的方式通路
  • 我們在chrome的開發者工具下的Network可以看到隻請求了一個頁面。
React Lazy 和 Suspense
  • 但是當我們點選加載js,你會發現test.js會以動态的方式加入到代碼中,同時執行了test函數,使頁面的内容發生了變化。
    React Lazy 和 Suspense
  • React.lazy

    和常用的三方包

    react-loadable

    ,都是使用了這個原理,然後配合webpack進行代碼打包拆分達到異步加載,這樣首屏渲染的速度将大大的提高。
  • 由于

    React.lazy

    不支援服務端渲染,是以這時候

    react-loadable

    就是不錯的選擇。

React.lazy 使用

  • 下面示例代碼使用create-react-app腳手架搭建:
  • OtherComponent.jsx

    檔案内容
// 普通的子元件
import React from 'react';
const OtherComponent = ()=>{
    return(
        <div>我已加載</div>
    )
}
           
  • App.jsx

    檔案内容
import React, {Component} from 'react';
const OtherComponent = React.lazy(()=>import('./OtherComponent'));
class App extends Component{
    constructor(props){
        super(props);
        this.state = {};
    }
    render(){
        return (
            <div>
                <OtherComponent />
            </div>
        )
    }
}
export default App;
           
  • index.js

    檔案内容
import ReactDOM  from 'react-dom'
import App from './Lazy/App';

ReactDOM.render(
    <App  />,
    document.getElementById('root')
)
           
  • 運作結果:
    React Lazy 和 Suspense
    這是最簡單的

    React.lazy

    ,但是這樣頁面會報錯。這個報錯提示我們,在React使用了

    lazy

    之後,會存在一個加載中的空檔期,React不知道在這個空檔期中該顯示什麼内容,是以需要我們指定。接下來就要使用到

    Suspense

Suspense

如果在

App

渲染完成後,包含

Other

的子產品還沒有被加載完成,我們可以使用加載訓示器為此元件做優雅降級。這裡我們使用

Suspense

元件來解決。
  • 這裡将

    App

    元件改一改
import React, {Suspense,Component} from 'react';
const OtherComponent = React.lazy(()=>import('./OtherComponent'));
class App extends Component{
    constructor(props){
        super(props);
        this.state = {
            visible:false
        };
    }
    render(){
        return (
            <div>
                <button onClick={() => {
          this.setState({ visible: true })
        }}>
          加載OtherComponent元件
        </button>
        <Suspense fallback={<div>Loading...</div>}>
          {
            this.state.visible
              ?
              <OtherComponent />
              :
              null
          }
        </Suspense>
            </div>
        )
    }
}
export default App;
           
  • 我們指定了空檔期使用Loading展示在界面上面,等

    OtherComponent

    元件異步加載完畢,把

    OtherComponent

    元件的内容替換掉Loading上。
React Lazy 和 Suspense
React Lazy 和 Suspense
  • 可以從上面圖檔看出,當點選加載的時候,頁面的head會插入``這段代碼,發出一個get請求,頁面開始顯示loading,去請求

    2.chunk.js

    檔案
  • 請求結束傳回内容就是

    OtherComponent

    元件的内容,隻是檔案名稱和檔案内容經過webpack處理過
  • 注意:

    Suspense

    使用的時候,

    fallback

    一定是存在且有内容的, 否則會報錯。