通过手动编写skeleton,在fetch数据时显示skeleton loading,数据拉取成功隐藏skeleton 先看下效果图 在component下创建页面对应的skeleton,然后通过在index.js中export输出,在需要使用skeleton的页面
通过手动编写skeleton,在fetch数据时显示skeleton loading,数据拉取成功隐藏skeleton
先看下效果图
在component下创建页面对应的skeleton,然后通过在index.js中export输出,在需要使用skeleton的页面中引入。
代码结构
charity-web |--- components |---Skeleton |---HomeProject.js home页项目列表 |---index.js 导出所有skeleton |---ProjectCard.js 项目列表item |---HomeListing.js 项目列表页 |--- pages |---index.js |---listing.js |--- redux |---app |---project |---index.js |---rootSaga.js
skeleton部分代码
- skeleton/index.js文件
import HomeProjectSkeleton from './HomeProject' import ProjectListingSkeleton from './ProjectListing' import PromotionItemSkeleton from './PromotionItem' export { PromotionItemSkeleton, HomeProjectSkeleton, ProjectListingSkeleton }
- skeleton/homeproject.js文件
import { Col, Row } from 'antd' import React, { Component } from 'react' import styled from 'styled-components' import mediaQuery from '../../utils/mediaQuery' import ProjectCard from './ProjectCard' const Container = styled.div` .projects { padding-top: 32px; ${mediaQuery.tablet} { padding-top: 24px; } ${mediaQuery.mobile} { padding-top: 24px; } } .projectWrapper { padding-bottom: 24px; } ` class HomeProject extends Component { render() { const items = [0, 1, 2, 3, 4] return ( <Container> <div className='projects'> <div className='max-width'> <Row type='flex' justify='start' gutter={24}> {items.map(i => { return ( <Col xs={24} md={12} xl={8} className='projectWrapper' key={`p_${i}`} > <ProjectCard /> </Col> ) })} </Row> </div> </div> </Container> ) } } export default HomeProject
- skeleton/projectlisting.js文件
import { Col, Row } from 'antd' import React, { Component } from 'react' import ProjectCard from './ProjectCard' class ProjectListing extends Component { render() { const items = [0, 1, 2, 3, 4] return ( <Row type='flex' justify='start' gutter={24}> {items.map(i => { return ( <Col xs={24} md={24} xl={24} className='projectWrapper' key={`p_${i}`} > <ProjectCard listStyle /> </Col> ) })} </Row> ) } } export default ProjectListing
- skeleton/promotionitem.js文件
import React, { Component } from 'react' import styled from 'styled-components' import mediaQuery from '../../utils/mediaQuery' const Container = styled.div` width: 100vw; height: 37.5vw; background-color: #f4f4f4; ${mediaQuery.mobile} { height: 56.25vw; } ` class PromotionItem extends Component { render() { return <Container /> } } export default PromotionItem
在页面中应用skeleton
1、首先引入skeleton
import { HomeProjectSkeleton, PromotionItemSkeleton } from '../components/Skeleton/index'
2、在render函数中,通过 this.props.isFetching判断是否显示skeleton
{process.env.usePromoItem ? ( this.props.isFetching ? ( <PromotionItemSkeleton /> ) : ( <Swiper slides={this.props.promoItems} /> ) ) : ( this.renderHeroProject() )} {this.props.isFetching ? ( <HomeProjectSkeleton /> ) : ( (this.renderHighlightedProjects(), this.renderOtherProjects()) )}
3、在reduces.js中,当getHomePageDataRequest拉取数据的时候,设置isFetching为true,getHomePageDataSucceeded获取成功后,将isFetching修改为false
import { getHomePageDataRequest, getHomePageDataSucceeded, } from './actions' export const projectInitialState = { fetching: { getHomepageData: false, getSearchListingPageData: false } } const projectReducer = handleActions( { [getHomePageDataRequest]: state => { return { ...state, fetching: { getHomepageData: true } } }, [getHomePageDataSucceeded]: (state, action) => { return { ...state, fetching: { getHomepageData: false } } }, } projectInitialState ) export default projectReducer
4、这样,在页面中mapStateToProps中我们可以拿到isFetching的状态,从而在数据获取成功之前显示skeleton
const mapStateToProps = ({ appState, projectState, paymentState }, props) => ({ isFetching: projectState.fetching.getHomepageData })
总结
以上,就是对skeleton在项目中的应用,当然通过以上这种方式实现的skeleton,有一个不好的地方是,如果页面结构变化,我们同时也需要更新sekleton的结构,这是比较麻烦的地方。