一次react滚动列表的实践---兼容ios安卓
一、背景
近期项目改版,对原有的h5页面进行了重新设计,数据呈现变成了瀑布流。希望新版兼容ios和安卓两端的情况下,无限制的刷新加载数据。大致效果如下:

整个页面分4部分:
- 顶部导航
- 步数状态卡片
- 用户信息卡片
- 滚动列表
期望效果:列表滚动到用户信息卡片消失后,展示另一个吸顶的导航栏。
效果如下:

分析可以发现,首先我们要做的就是适配iPhone X,其次我们需要监听列表的滚动高度,在pc和安卓上监听滚动事件是没有问题的,但是ios上滚动过程中不会触发scroll事件,而是滚动结束后会触发onscrollend事件,这就不能满足实时监听高度的要求。经过简单调研,决定站在巨人的肩膀上,通过iscroll、better-scroll等js库实现。这两个库都是解决各种滚动兼容的js库,很多常见的轮播、picker组件都是基于这些库封装的。顺便说一句,还有个库也不错(simulation-scroll-y)
二、进入正题
- 1.适配iPhone X
PhoneX的适配,在iOS 11中采用了viewport-fit的meta标签作为适配方案;viewport-fit的默认值是auto。react app的渲染内容都在id为root的 div里面。我们给这个div加上iphoneX的safe-area-inset属性即可。更多相关内容,这篇文章写的挺详细
<meta name='viewport' content='width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover' />
#root{
height:100vh;
padding-top: constant(safe-area-inset-top);
padding-left: constant(safe-area-inset-left);
padding-right: constant(safe-area-inset-right);
padding-bottom: constant(safe-area-inset-bottom);
padding-top: env(safe-area-inset-top);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
padding-bottom: env(safe-area-inset-bottom);
}
2.页面
页面结构不多说,比较基础。
div.container-> div#wrapper->div.list->div.list-item
值得注意的是,wrapper需要设置绝对定位。同时,通过transform: translateZ(0);开启硬件加速,浏览器在渲染时会通过GPU进行渲染。有效缓解安卓端滚动卡顿的问题,类似的css还有不少,css硬件加速不要滥用,否则会导致不该使用gpu的layer使用gpu,占用内存过高,导致页面卡顿,甚至黑屏,一般情况下,给不同的硬件加速元素添加一个不同的z-index属性可以解决。-webkit-overflow-scrolling: touch使ios滚动顺滑。
// 初始化BScroll伪代码,生产慎用:
import BScroll from 'better-scroll'; this.myScroll = new BScroll('#wrapper', {
mouseWheel : true,
// 无需scrollbar
scrollbar : false,
// propType属性设置为3在惯性动画期间也触发onscroll事件
probeType : 3,
// 允许滚动列表内可点击、touch
click : true,
tap : true,
// 上拉加载,正值自动触发加载
pullUpLoad : {
threshold: 50
}
});
一开始,我将better-scroll初始化代码放在container组件的componentDidMount函数中,但由于初始数据也在这个函数获取,导致当返回较慢的时候初始化的#wrapper没有内容,此时需要手动点击加载更多才展现数据,不符合预期。所以考虑将初始化代码放到list组件渲染完成之后的componentDidUpdate函数中。list组件渲染完成后,就可以初始化我们的滚动类,这里使用的better-scroll,iscroll使用类似。具体参考上面链接。
#wrapper {
position:absolute;
top:0;
left:0;
width:100vw;
overflow:auto;
height: 100vh;
transform: translateZ(0);
z-index: 33;
-webkit-overflow-scrolling: touch
}
具体的,可以将初始化代码放在list组建的container组件的handleScrollRefresh函数。这个函数作为props传到list组件,在list组件的componentDidUpdate钩子里面执行:
container组件:
handleScrollRefresh () {
if (this.myScroll) {
this.myScroll.refresh();
console.log('refreshed ');
} else {
console.log('initialized');
this.myScroll = new BScroll('#wrapper', {
...//初始化参数
});
this.myScroll.on('scroll',this.handleScroll, 10);
this.myScroll.on('pullingUp', this.loadMore);
}
}
list 组件:
componentDidUpdate () {
if (this.props.onRefresh) {
this.props.onRefresh();
}
}
网上很多滚动卡顿的情况,大都是加载数据后没有执行refresh导致的。同时,加载数据成功后我们需要调用scroll的finishPullUp方法。下次上拉才能继续加载数据。这样,每当加载新的数据后,list组件就会执行componentDidUpdate,此时就调用了scroll的finishPullUp、refresh函数,使用起来无比顺滑。
三、优化
和大多数滚动处理一样,better-scroll的scroll事件也会频繁触发,这对性能还是有一定影响的,毕竟我们不需要过于频繁的执行回调函数。
throttle (func, delay) {
let lastTime = null;
return function () {
let context = this;
let args = arguments;
let now = new Date().getTime();
if (!lastTime || (now - lastTime) > delay) {
lastTime = now;
func.apply(context, args);
}
};
};
不想写直接使用lodash也可以:
//不精准的每秒十次
this.myScroll.on('scroll', this.throttle(this.handleScroll, 100));
- 函数绑定,不传参的情况下在constructor中绑定this。而不是在render中使用this.xxx.bind(this)。
- list 图片大小限制,本次由于部分列表item图片过大,在安卓上导致黑屏的问题出现。排查了很久才发现这个问题。通过在图片url拼接参数限制大小解决了这个问题。
最后
感觉写得好乱,做事情和写文章果然是两回事。。。
有兴趣可以访问:https://3hours.taobao.com/new...
一起来做公益吧!
来源:https://segmentfault.com/a/1190000017520404
一次react滚动列表的实践---兼容ios安卓的更多相关文章
- Textarea输入字数限制(兼容iOS&安卓)
最近在做一个微信公众号的页面,其中有对textarea做输入字数限制,而且需要兼容iOS和安卓手机,下面直接贴代码: <!DOCTYPE html> <html lang=" ...
- 手机端两端对齐,兼容ios,安卓
.div-title p label{ text-align: justify; width: 18%; display: inline-block; text-align-last: justify ...
- H5和PC实现点击复制当前文字的功能,兼容ios,安卓
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 利用React Native 从0到1 开发一款兼容IOS和android的APP(仿造京东)
最近有一部电视剧叫做<微微一笑很傻逼>里面有个男猪脚,人们都叫他大神~我觉得吧~大神是相对的~所以~啥事都得谦虚! 好了 今天介绍的是如何从0到1利用React Native开发一款兼容I ...
- Jquery制作--循环滚动列表
自己模仿JQ插件的写法写了一个循环滚动列表插件,支持自定义上.下.左.右四个方向,支持平滑滚动或者间断滚动两种方式,都是通过参数设置.JQ里面有些重复的地方,暂时没想到更好的方法去精简.不过效果还是可 ...
- react 组件列表
let data=[ [ '同时入选IMDB250和豆瓣电影250的电影', '带你进入不正常的世界', '用电[影]来祭奠逝去的岁月', '女孩们的故事[电影]', '', '使用 App [找电影 ...
- React Native 列表的总结
React Native 列表的总结 FlatList和SectionList都是React Native中高性能的列表组件.这些新的列表组件在性能方面都有了极大的提升, 其中最主要的一个是无论列表有 ...
- 【js】我们需要无限滚动列表吗?
无限滚动列表,顾名思义,是能够无限滚动的列表(愿意是指那些能够不断缓冲加载新数据的列表的).但是,我们真的需要这样一个列表吗?在PC端,浏览器的性能其实已经能够满足海量dom节点的渲染刷新(笔者经过简 ...
- React Native入门——布局实践:开发京东client首页(一)
有了一些对React Native开发的简单了解,让我们从实战出发.一起来构建一个简单的京东client. 这个client是仿照之前版本号的京东client开发的Android版应用,来源于CSDN ...
随机推荐
- nginx/iptables动态IP黑白名单实现方案
nginx/iptables动态IP黑白名单实现方案 一.手动封IP步骤 1.Nginx手动封IP 1.获取各个IP访问次数 awk '{print $1}' nginx.access.log |so ...
- SourceTree的基本使用-git on mac
SourceTree的基本使用 学习了:https://www.cnblogs.com/tian-xie/p/6264104.html
- 好工具MyEclise2016 CI下载
地址:http://pan.baidu.com/s/1gfBw9Ab 安装后,点开crack目录,按步骤走. 下面是我安装成功的画面.
- 翻翻git之---一个丰富的通知工具类 NotifyUtil
转载请注明出处王亟亟的大牛之路 P1(废话板块.今天还加了个小广告) 昨天出去浪,到家把麦麦当当放出来玩一会就整到了12点多..早上睡过头了. .简直心酸. ... 近期手头上有一些职位能够操作,然后 ...
- mixare的measureText方法在频繁调用时抛出“referencetable overflow max 1024”的解决方式
这几天在搞基于位置的AR应用,採用了github上两款开源项目: mixare android-argument-reality-framework 这两个项目实现机制大致同样.我选取的是androi ...
- bootcamp安装win7的详细步骤 (光盘安装)
bootcamp安装win7的详细步骤 首先是要您确定以下内容(1)您的Mac系统下是一个盘符,也就是“macintosh hd”一个磁盘.如果不是的话,首先您需要做的是备份您分区下面的资料,让磁 ...
- 跟我一起写 Makefile(一)[转]
原文链接 http://bbs.chinaunix.net/thread-408225-1-1.html(出处: http://bbs.chinaunix.net/) 陈皓 概述—— 什么是makef ...
- 摩托罗拉SE955 One Discrete Length,Two Discrete Lengths,Length Within Range 相关解释
motorola scanner datasheet相关解释(下面通过Simple Serial Interface(SSI)进行设置,非扫描官方datasheet的设置条码): One Discre ...
- TOML简介 (转)
TOML的由来 配置文件的使用由来已久,从.ini.XML.JSON.YAML再到TOML,语言的表达能力越来越强,同时书写便捷性也在不断提升. TOML是前GitHub CEO, Tom Prest ...
- java 面试总结
1.static变量与实体变量的差别? static是静态变量,static能够通过类名直接訪问 内存方面的不同:static在定义的时候jvm就会分配空间, 而实体变量仅仅有在创建对象的时候才会去分 ...