阅读 173

实现一个React通用骨架屏组件(vue骨架屏组件)

Demo

先看个demo 大概了解下最终的产物及其使用方式

GIF 2021-12-5 21-41-15.gif

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就可以实现自动生成骨架了。

但在具体的使用上,我们可能只需要结构前几层的结构而不需要模拟整颗树的结构,也有可能自动生成的样式太丑我们需要定制其节点样式,还有可能我们不需要关注一些浮层类的内容或者说想忽略某一个节点

所以大概需要实现以下几个功能

  1. 设定递归深度

  2. 提供忽略节点的方法

  3. 提供定制骨架节点样式的方法

具体实现

首先定义一个组件函数来决定是渲染骨架屏还是真实元素

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 />;   } } 复制代码

createModalSkeleton下面包住的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>     );   } }; 复制代码

完整代码及其使用文档


作者:magic_zhu
链接:https://juejin.cn/post/7038221975902240805

 伪原创工具 SEO网站优化  https://www.237it.com/ 


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐