React組件惰性渲染淺析

什麼是惰性渲染

惰性渲染實際上是一種渲染優化方式之一,簡單來講一個React組件,好比Drawer抽屜組件,開始是抽屜是不顯示的,也就是說visible這個prop若是初始爲false的話,那麼在render裏就return null,也就是說這個抽屜組件就不渲染,dom樹中就沒有對應的結構。而後當你點擊一個按鈕設置visible屬性爲true時,此時才渲染抽屜組件,而後你又點擊按鈕,置visible爲false,此時組件隱藏,可是dom中仍然存在,這樣一個過程的好處在於初始加載時能夠大大減小渲染的負擔,提交頁面加載速度,下面就經過Antd的Drawer源碼一探究竟react

源碼解析

其實仔細想一想就能夠發現咱們只需一個變量記錄該組件是否是第一次加載便可,若是是第一次加載就return null,不然就渲染組件,後續的顯隱就經過display:none來切換便可,可是Drawer組件作法有區別git

首先咱們找到Drawer的代碼, 查看index.ts,發現引用的是DrawerWrapper組件,直接跳到render方法查看,實際上是一個Portal組件,能夠猜到Portal組件是封裝了React原生的Portal用法,必須用portal由於須要把Drawer掛在body上github

return (
      <Portal visible={open} forceRender={$forceRender} getContainer={getContainer} wrapperClassName={wrapperClassName} > {({ visible, afterClose, ...rest }: IChildProps) => ( // react 15,componentWillUnmount 時 Portal 返回 afterClose, visible. <Child {...props} {...rest} open={visible !== undefined ? visible : open} afterVisibleChange={afterClose !== undefined ? afterClose : props.afterVisibleChange} handler={handler} onClose={this.onClose} onHandleClick={this.onHandleClick} /> )} </Portal> ); 複製代碼

這裏的visible屬性的open就是經過用戶傳入Drawer組件的visible這個prop衍生出來的,控制Portal的顯示隱藏,這裏並無惰性渲染的蹤影,那麼繼續深刻Portal的代碼,在開頭髮現Portal是rc-util裏的,其實antd全部組件都是封裝自rc開頭的一系列組件antd

import Portal from 'rc-util/lib/PortalWrapper';
複製代碼

找到PortalWrapper組件的render,真相大白app

render() {
    const { children, forceRender, visible } = this.props;
    let portal = null;
    const childProps = {
      getOpenCount: () => openCount,
      getContainer: this.getContainer,
      switchScrollingEffect: this.switchScrollingEffect,
    };
    
    // 省略部分代碼
    
    if (forceRender || visible || this._component) {
      portal = (
        <Portal getContainer={this.getContainer} ref={this.savePortal}> {children(childProps)} </Portal>
      );
    }
    return portal;
  }
複製代碼

這裏能夠看到用了一個portal變量,初始visible爲false的話,直接走最後的return portal,返回null,不渲染任何東西,而後visible一旦設爲true,則走if分支,裏面的關鍵在於ref引用 那個savePortaldom

savePortal = c => {
    // Warning: don't rename _component
    // https://github.com/react-component/util/pull/65#discussion_r352407916
    this._component = c;
  };

複製代碼

這裏一旦渲染組件,則保存Portal的引用到_component這個私有變量中,而後visible再次爲false,則仍是走if分支,由於this._component不是null,因此達到了惰性渲染的目的優化

相關文章
相關標籤/搜索