React實現一個通用骨架屏組件示例

骨架屏是什麼?

找到這裡的同志,或多或少都對骨架屏有所瞭解,請容許我先囉嗦一句。骨架屏(Skeleton Screen)是一種優化用戶弱網體驗的方案,可以有效緩解用戶等待的焦躁情緒。

Demo

先看個demo 大概瞭解下最終的產物及其使用方式

npm install obiusm-react-components
import { Skeleton } from 'obiusm-react-components';
  <Skeleton isVisible={true}>
    <div className="wrapper">
      <div className="content1"></div>
      <div data-skeleton-ignore={true}>123456</div>
      <div className="content2"></div>
      <div className="content3" data-skeleton-style={{ width: '50%' }}></div>
    </div>
  </Skeleton>

隻需要在自己寫的組件外面包一層決定其是否顯示就可以瞭

設計思路

骨架可以在真實內容沒有加載出來前讓用戶提前感知,可以提高用戶體驗 如果我們每次寫組件的時候都要為其定制骨架,那就顯得相當繁瑣

得益於React props的這種數據數據傳遞方式,我們在props中可以輕松拿到整顆ReactElement的樹。 那麼我們隻需要去遞歸遍歷這個樹從而去模仿其結構,復制其class就可以實現自動生成骨架瞭。

但在具體的使用上,我們可能隻需要結構前幾層的結構而不需要模擬整顆樹的結構,也有可能自動生成的樣式太醜我們需要定制其節點樣式,還有可能我們不需要關註一些浮層類的內容或者說想忽略某一個節點

所以大概需要實現以下幾個功能

  • 設定遞歸深度
  • 提供忽略節點的方法
  • 提供定制骨架節點樣式的方法

具體實現

首先定義一個組件函數來決定是渲染骨架屏還是真實元素

function Skeleton(props: Props) {
  if (!props) {
    return <div />;
  }
  if (props.isVisible) {
    return createModal(props.children, props.depth || 4, 0);
  } else {
    return props.children ? props.children : <div />;
  }
}

createModal 對Skeleton下面包住的div進行遞歸遍歷, 每次遞歸的時候將current+1並傳遞下去,這樣我們可以判斷已經遞歸瞭幾層瞭 判斷一下每個節點上data-skeleton-ignore是否有data-skeleton-style從而特殊處理就可以瞭

const createModal = (child: ReactElement, depth: number, current: number) => {
  if (
    depth === current ||
    (child && child.props && child.props['data-skeleton-ignore'])
  ) {
    return;
  }
  if (
    child &&
    child.props &&
    child.props.children &&
    Array.isArray(child.props.children) &&
    current < depth - 1
  ) {
    return (
      <div
        className={`${
          child.props.className !== undefined ? child.props.className : ''
        } ${'react-skeleton'}`}
        style={
          child.props && child.props['data-skeleton-style']
            ? child.props['data-skeleton-style']
            : {}
        }
        key={Math.random() * 1000}
      >
        {child.props.children && child.props.children.length > 0
          ? child.props.children.map((child: any) => {
              return createModal(child, depth, current + 1);
            })
          : '*'}
      </div>
    );
  } else {
    return (
      <div
        className={`${
          child.props && child.props.className ? child.props.className : ''
        } ${'react-skeleton2'}`}
        style={
          child.props && child.props['data-skeleton-style']
            ? child.props['data-skeleton-style']
            : {}
        }
        key={Math.random() * 1000}
      >
        *
      </div>
    );
  }
};

完整代碼及其使用文檔

完整代碼 obiusm-react-components

文檔 https://magic-zhu.github.io/obiusm-react-components-docs/components/skeleton/

到此這篇關於React實現一個通用骨架屏組件示例的文章就介紹到這瞭,更多相關React 骨架屏內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: