taro小程序添加骨架屏的实现代码


Posted in Javascript onNovember 15, 2019

最近做了一些小程序方面的性能优化,如分包加载,添加骨架屏等,这次主要说一下骨架屏的相关内容。

关于骨架屏,有三种方法:

1.直接请UI同学帮忙P张图,当做loading图放上去。这种方法简单粗暴,但是需要请人帮忙~
2.根据每个页面,自己写一套相同的代码来覆盖样式。这种方法的工程量,你懂的~
3.能不能写个组件呢?该组件自动获取元素位置大小信息来渲染,数据返回后将其卸载。

下面主要说第三种方法~

主框架采用taro,一套代码兼容多端,但是今天这个代码,需要考虑兼容性~

根据上面的思路,我们首先要找到骨架屏的容器,然后找到需要P成灰色的元素,获取该元素的位置大小信息,最后就是渲染了~

获取元素,taro提供了API,Taro.createSelectorQuery()。通过这个API返回一个SelectorQuery对象实例,然后再通过selectAll()来查找骨架中带有特定类的class名,查找之后通过boundingClientRect()获取元素的位置大小信息,把这些信息存放在数组中。
我这边写了两个类,一个是skeleton-radius,渲染圆形;一个是skeleton-rect,渲染长方形。后续大家可以自行扩展。

文字有点多,大家可能看着有点云里雾里的,下面上代码~

// 百度小程序目前不支持跨自定义组件的后代选择器: >>>
  // 但是H5使用后代选择器(.the-ancestor .the-descendant)的时候,可以自动识别自定义组件内的后代
  // 微信小程序支持跨自定义组件都后代选择器(.the-ancestor >>> .the-descendant),可修改为如`.${this.props.selector} >>> .${this.props.selector}-radius`
  if (process.env.TARO_ENV === 'weapp') {
    Taro.createSelectorQuery().selectAll(`.${this.props.selector} >>> .${this.props.selector}-radius`)
      .boundingClientRect().exec(rect => {
        that.setState({
          radiusList: rect[0]
        });
      });
  }
  else {
    Taro.createSelectorQuery().selectAll(`.${this.props.selector} .${this.props.selector}-radius`)
    .boundingClientRect().exec(rect => {
      that.setState({
        radiusList: rect[0]
      });
    });
  }

大家也看到上面的注释了,如果要在多端运行,可先判断环境,根据环境使用不同的选择器。上面代码是实现一个圆形的灰色区域~大家如果有多个形状的需求的话,可以简单封装一个函数,这里我就不再细说了,具体的可以到Demo详细查看~
细说一下后代选择器的兼容性问题:

  1. 百度小程序目前不支持跨自定义组件的后代选择器: >>>。
  2. 但是H5使用后代选择器(.the-ancestor .the-descendant)的时候,可以自动识别自定义组件内的后代。使用自定义组件时,外层是否有元素包裹,都可识别到自定义组件内部的指定类选择器。
  3. 微信小程序支持跨自定义组件的后代选择器(.the-ancestor >>> .the-descendant),但使用自定义组件时,外层不能嵌套元素,否则无法识别。

接下来就是渲染了,这个比较简单,直接上代码~这里背景色和将要P成条状等的元素的背景色都可以在使用组件时自定义传入,也可以不传,有默认色~

<View className='skeleton-container' style={{background: `${bgColor}`}}>
      {
        radiusList.map(radiusItem => (
          <View className='skeleton-item skeleton-item-radius' style={{width: `${radiusItem.width}PX`, height: `${radiusItem.height}PX`,
            background: `${itemColor}`, top: `${radiusItem.top}PX`, left: `${radiusItem.left}PX`}}
          />
        ))
      }
      {
        rectList.map(rectItem => (
          <View className='skeleton-item' style={{width: `${rectItem.width}PX`, height: `${rectItem.height}PX`,
            background: `${itemColor}`, top: `${rectItem.top}PX`, left: `${rectItem.left}PX`}}
          />
        ))
      }
    </View>

到这里,组件已经完成了,使用的时候可以直接引入组件,然后传入selector就可以了,注意,由于数据是动态获取的,页面开始为空,这里就需要mock一些假数据来填充页面了~要覆盖的元素类名必须和组件中的图形类保持一致~

<View className='container' style={{fontSize: '20PX'}}>
      {
        showSkeleton && <Skeleton
          selector='skeleton'
          bgColor='pink'
          itemColor='skyblue'
        />
      }
      <View className='skeleton'>
        <View className='userInfo'>
          <Image
            src={userInfo.avatarUrl}
            alt='用户头像'
            className='userInfo-avatar skeleton-radius'
          />
          <Text>{userInfo.nickName}</Text>
        </View>
        <View>
          {
            list.map(item => (
              <View className='skeleton-rect' style={{marginBottom: '30PX'}}>{item}</View>
            ))
          }
        </View>
        {/* 自定义组件外层最好没有元素包裹,否则微信小程序无法识别,但是H5可以识别 */}
        <List />
      </View>
    </View>

看到注释了吗?使用自定义组件时一定要注意噢~自定义组件若被元素报错,微信小程序无法识别到自定义组件内的图形类!!!

最后要说一下适合使用骨架屏的场景:页面结构简单,元素的宽高固定~若元素宽高不固定的话,你写的mock假数据可能和实际渲染出来的页面差距较大,例如瀑布流~

好了,这次的一些收获就到这里了~大家如果有更好的方法,可以留言交流~最后,附上完整的代码地址~

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery 页面全选框实践代码
Apr 02 Javascript
IE6/7/8/9不支持exec的简写方式
May 25 Javascript
js获取浏览器的可视区域尺寸的实现代码
Nov 30 Javascript
Knockoutjs快速入门(经典)
Dec 24 Javascript
一个简单的jQuery计算器实现了连续计算功能
Jul 21 Javascript
jquery实现简单Tab切换菜单效果
Jul 17 Javascript
jQuery实现的导航下拉菜单效果
Jul 04 Javascript
本地Bootstrap文件字体图标引入却无法显示问题的解决方法
Apr 18 Javascript
JS沙箱模式实例分析
Sep 04 Javascript
微信小程序的部署方法步骤
Sep 04 Javascript
vue动画之点击按钮往上渐渐显示出来的实例
Sep 29 Javascript
Vue表单绑定的实例代码(单选按钮,选择框(单选时,多选时,用 v-for 渲染的动态选项)
May 13 Javascript
详解Angular Karma测试的持续集成实践
Nov 15 #Javascript
Javascript 类型转换、封闭函数及常见内置对象操作示例
Nov 15 #Javascript
JavaScript定时器常见用法实例分析
Nov 15 #Javascript
解决Layui 表格自适应高度的问题
Nov 15 #Javascript
layui前端时间戳转化实例
Nov 15 #Javascript
JavaScript变量基本使用方法实例分析
Nov 15 #Javascript
JavaScript字符串处理常见操作方法小结
Nov 15 #Javascript
You might like
PHP4实际应用经验篇(1)
2006/10/09 PHP
php知道与问问的采集插件代码
2010/10/12 PHP
PHP根据传来的16进制颜色代码自动改变背景颜色
2014/06/13 PHP
ThinkPHP提交表单时默认自动转义的解决方法
2014/11/25 PHP
php编译安装php-amq扩展简明教程
2016/06/25 PHP
PHP图片水印类的封装
2017/07/06 PHP
TP5框架model常见操作示例小结【增删改查、聚合、时间戳、软删除等】
2020/04/05 PHP
新手入门常用代码集锦
2007/01/11 Javascript
JS简单实现登陆验证附效果图
2013/11/19 Javascript
js控制表单不能输入空格的小例子
2013/11/20 Javascript
jquery 页面滚动到底部自动加载插件集合
2014/01/31 Javascript
JavaScript fontsize方法入门实例(按照指定的尺寸来显示字符串)
2014/10/17 Javascript
深入理解JavaScript系列(38):设计模式之职责链模式详解
2015/03/04 Javascript
jQuery获得子元素个数的方法
2015/04/14 Javascript
javascript实现禁止复制网页内容汇总
2015/12/30 Javascript
js实现楼层效果的简单实例
2016/07/15 Javascript
浅谈javascript中的Function和Arguments
2016/08/30 Javascript
用瀑布流的方式在网页上插入图片的简单实现方法
2016/09/23 Javascript
ionic进入多级目录后隐藏底部导航栏(tabs)的完美解决方案
2016/11/23 Javascript
Layui实现主窗口和Iframe层参数传递
2019/11/14 Javascript
浅析vue cli3 封装Svgicon组件正确姿势(推荐)
2020/04/27 Javascript
js实现简单扫雷
2020/11/27 Javascript
vue+element_ui上传文件,并传递额外参数操作
2020/12/05 Vue.js
python使用urllib2实现发送带cookie的请求
2015/04/28 Python
Python编程之string相关操作实例详解
2017/07/22 Python
30行Python代码实现高分辨率图像导航的方法
2020/05/22 Python
Python 实现将numpy中的nan和inf,nan替换成对应的均值
2020/06/08 Python
python3.7添加dlib模块的方法
2020/07/01 Python
Python 实现简单的客户端认证
2020/07/29 Python
一款利用纯css3实现的win8加载动画的实例分析
2014/12/11 HTML / CSS
欧克利英国官网:Oakley英国
2019/08/24 全球购物
AJAX应用和传统Web应用有什么不同
2013/08/24 面试题
2014年庆元旦活动方案
2014/02/15 职场文书
公司市场部岗位职责
2015/04/15 职场文书
公共场所卫生管理制度
2015/08/05 职场文书
《金色的草地》教学反思
2016/02/17 职场文书