React實(shí)現(xiàn)一個(gè)通用骨架屏組件示例
骨架屏是什么?
找到這里的同志,或多或少都對(duì)骨架屏有所了解,請(qǐng)容許我先啰嗦一句。骨架屏(Skeleton Screen)是一種優(yōu)化用戶弱網(wǎng)體驗(yàn)的方案,可以有效緩解用戶等待的焦躁情緒。
Demo
先看個(gè)demo 大概了解下最終的產(chǎn)物及其使用方式

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>
只需要在自己寫的組件外面包一層決定其是否顯示就可以了
設(shè)計(jì)思路
骨架可以在真實(shí)內(nèi)容沒(méi)有加載出來(lái)前讓用戶提前感知,可以提高用戶體驗(yàn) 如果我們每次寫組件的時(shí)候都要為其定制骨架,那就顯得相當(dāng)繁瑣
得益于React props的這種數(shù)據(jù)數(shù)據(jù)傳遞方式,我們?cè)趐rops中可以輕松拿到整顆ReactElement的樹(shù)。 那么我們只需要去遞歸遍歷這個(gè)樹(shù)從而去模仿其結(jié)構(gòu),復(fù)制其class就可以實(shí)現(xiàn)自動(dòng)生成骨架了。
但在具體的使用上,我們可能只需要結(jié)構(gòu)前幾層的結(jié)構(gòu)而不需要模擬整顆樹(shù)的結(jié)構(gòu),也有可能自動(dòng)生成的樣式太丑我們需要定制其節(jié)點(diǎn)樣式,還有可能我們不需要關(guān)注一些浮層類的內(nèi)容或者說(shuō)想忽略某一個(gè)節(jié)點(diǎn)
所以大概需要實(shí)現(xiàn)以下幾個(gè)功能
- 設(shè)定遞歸深度
- 提供忽略節(jié)點(diǎn)的方法
- 提供定制骨架節(jié)點(diǎn)樣式的方法
具體實(shí)現(xiàn)
首先定義一個(gè)組件函數(shù)來(lái)決定是渲染骨架屏還是真實(shí)元素
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 對(duì)Skeleton下面包住的div進(jìn)行遞歸遍歷, 每次遞歸的時(shí)候?qū)urrent+1并傳遞下去,這樣我們可以判斷已經(jīng)遞歸了幾層了 判斷一下每個(gè)節(jié)點(diǎn)上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>
);
}
};
完整代碼及其使用文檔
文檔 https://magic-zhu.github.io/obiusm-react-components-docs/components/skeleton/
到此這篇關(guān)于React實(shí)現(xiàn)一個(gè)通用骨架屏組件示例的文章就介紹到這了,更多相關(guān)React 骨架屏內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React結(jié)合Drag?API實(shí)現(xiàn)拖拽示例詳解
這篇文章主要為大家介紹了React結(jié)合Drag?API實(shí)現(xiàn)拖拽示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
react-native ListView下拉刷新上拉加載實(shí)現(xiàn)代碼
本篇文章主要介紹了react-native ListView下拉刷新上拉加載實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
React官方團(tuán)隊(duì)完善原生Hook閉包陷阱
這篇文章主要為大家介紹了React官方團(tuán)隊(duì)出手,補(bǔ)齊原生Hook短板閉包陷阱的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
解析react?函數(shù)組件輸入卡頓問(wèn)題?usecallback?react.memo
useMemo是一個(gè)react hook,我們可以使用它在組件中包裝函數(shù)??梢允褂盟鼇?lái)確保該函數(shù)中的值僅在依賴項(xiàng)之一發(fā)生變化時(shí)才重新計(jì)算,這篇文章主要介紹了react?函數(shù)組件輸入卡頓問(wèn)題?usecallback?react.memo,需要的朋友可以參考下2022-07-07
Vite+React+TypeScript手?jǐn)]TodoList的項(xiàng)目實(shí)踐
本文主要介紹了Vite+React+TypeScript手?jǐn)]TodoList的項(xiàng)目實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05

