本文章是一个系列文章,以一个完整的可用于生产的实际项目探索微信小程序开发中我们经常会遇到的问题,希望能提供完美的解决方案,这次是本系列文章的第二篇了,以下列出该系列文章链接。
工作忙碌,难得有时间继续开发研究这个项目,目前完成了,基础设施开发及首页得开发,话不多说,老规矩,先来看下效果吧
这是根据页面布局自动生成得骨架屏,目前非常流行的一种提升体验的办法
为了能看到骨架屏的渲染,我调慢了所有接口的响应速度,因此演示响应较慢
整体效果还不错吧(沾沾自喜中~)
骨架屏的思路
骨架屏的实现思路相对较简单,使用方法也很方便
我们知道微信小程序已经开发了选择器功能,可以利用此特性获取到dom节点,为了能让骨架屏组件知道该如何绘制,我们需要做如下约定:
- 约定.skeleton样式类为骨架屏查找绘制节点的根节点
- 约定.skeleton-square样式类,表示绘制当前节点的骨架节点样式为方形(如商品卡片)
- 约定.skeleton-circular样式类,表示绘制当前节点的骨架节点为圆形(如logo)
- 约定.skeleton-cylinder样式类,表示绘制当前节点的骨架节点为长条形(如搜索框)
- 约定.skeleton-light与.skeleton-dark为块元素背景骨架样式
骨架屏的使用
首先我们需要引入skeleton组件到页面中,并且在页面根元素上加上.skeleton样式
<View className={classNames(styles.home, 'skeleton')}>
{initialize && <ComponentCommonSkeleton />}
</View>
然后在对应元素中加入不同的样式类,绘制骨架
<View className={classNames(styles.hotsale, 'skeleton-light')}>
<View className={styles.header}>
<View className={classNames(styles.title, 'skeleton-square')}>
今日热卖
</View>
<View className={classNames(styles.tip, 'skeleton-square')}>
每日推荐,超值抢购
</View>
</View>
</View>
骨架屏的实现
完整的实现逻辑,由于代码较多,不与全部给出,有兴趣的直接去仓库吧skeleton源码
我们来看一下关键代码,如何获取骨架节点
// 利用微信小程序的selectorQuery查找相关节点
selectAll = selector =>
new Promise(resolve =>
Taro.createSelectorQuery()
.selectAll(selector)
.boundingClientRect()
.exec(res => resolve(res[0])),
)
componentDidMount() {
const { selector } = this.props
// 利用微信小程序跨自定义组件选择器`>>>`获取节点信息
Promise.all([
this.selectAll(`.${selector} >>> .${selector}-light`),
this.selectAll(`.${selector} >>> .${selector}-dark`),
this.selectAll(`.${selector} >>> .${selector}-square`),
this.selectAll(`.${selector} >>> .${selector}-circular`),
this.selectAll(`.${selector} >>> .${selector}-cylinder`),
]).then(([lights, darks, squares, circulars, cylinders]) =>
// 存储节点信息,用于渲染骨架屏
this.setState({
lights,
darks,
squares,
circulars,
cylinders,
}),
)
}
获取到了相关节点信息,比如width,height,top,left等信息后,便可以利用绝对定位或者fixed绘制骨架了
当然这只能解决常驻组件的获取,对于一些动态组件,比如列表渲染我们该如何处理呢,这里是一个比较麻烦的问题,我们需要在数据还未获取之前,给列表数据设置部分默认数据
比如: 设置默认的props或者state,这样项目初始化时便会渲染默认数据,也就可以获取到节点了
该项目托管于github,如有需要,请自取weapp-clover,感谢关注,感谢star