一 Demo三端效果图

RN端 小程序端 h5端
仅实现了滑动到底部自动加载更多的长列表页作为演示功能
**
二 整体布局
2.1 标题栏
为了达到原生App的沉浸式效果,需要根据平台类型隐藏除小程序外其他平台的默认标题栏,在入口文件中配置:
config = {window: {//标题栏背景色navigationBarBackgroundColor:'#ffffff',//标题栏文本颜色navigationBarTextStyle:'black',//隐藏两端的默认标题栏,此时可以自定义标题栏navigationStyle: process.env.TARO_ENV === 'weapp' ?'default':'custom'}}
2.2 固定搜索条和tab切换条
render () {...return (<View className='page'><SearchBar/><TabBar tabs={tabs} onTabClick={this.onTabClick}/><List topDist={170} datas={datas} /></View>)}
页面根布局设置相对定位,搜索条和tab切换条设置绝对定位于页面顶部。
搜索条和tab切换条高度写死,两者高度和作为属性传入列表页,通过动态样式来设置列表页距离顶部的距离
2.3 列表页
ScrollView 标签来实现列表的滚动,高度必须显示的设置,RN端的长列表必须使用renderItem属性,因此利用文件条件编译,单独创建rn的列表组件文件,其核心代码如下:
<ScrollViewclassName={scrollWarp}style={{height}}data={datas}renderItem={({item,index}) =><View className={'itemWrap'}><Item item={item} index={index} key={index} />...</View>}scrollYkeyExtractor = {(item,index) => `${index}`}onScrollToUpper={this.onScrollToUpper.bind(this)}onScrollToLower={this.onScrollToLower.bind(this)}/>
2.4 视频封面和播放按钮
背景封面使用View相对定位+Image绝对定位实现
播放按钮居中利用一个和封面一样大小的透明蒙层作为容器,设置flex布局并设置内部子标签的垂直水平居中来实现
三 数据流
3.1 关注和取消关注
将mobx的数据模型注入到Item组件,以便于操作数据:
@inject('indexMod')@observerexport default class Item extends PureComponent
点击关注或者已关注按钮时,调用mobx数据模型中的方法,修改数据
onFollowClick(index,active,name) {const {indexMod} = this.propsindexMod.setFollowState(index, !active)Taro.showToast({title: (active?'取消关注':'已关注')+name ,icon:'none'});}
在mobx数据模型中根据id找到列表子数据并修改
setFollowState(index, isFollow) {this.list = this.list.map(item => {if (item.id === this.currentId) {item.res[index].data.author.follow.followed = isFollow}return item})}
3.2 加载更多
找到对应tab的数组,进行concat操作,将请求到的更多数据加到原来的数组中
if (isLoadMore) {//加载更多this.list = this.list.map(item => {if (item.id === this.currentId) {//找到后更新数据item.res = item.res.concat(res)}return item})} else {this.list.push({id, res})}
3.3 Tab切换
tab切换时,没有缓存数据的列表需要请求后台,然后进行内存缓存,减少tab重复切换时的网络请求
onTabClick = (tab) => {const { indexMod } = this.propsindexMod.currentId = tab.id//判断当前tab的列表数据是否被缓存过let hasCached = falseindexMod.list.map(data => {if(data.id === tab.id){hasCached = true}})//如果没有缓存当前tab数据,就去请求服务器if(!hasCached){indexMod.getDatas(tab.id)}indexMod.onTabClick(tab.id)}
