一 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的列表组件文件,其核心代码如下:
<ScrollView
className={scrollWarp}
style={{height}}
data={datas}
renderItem={({item,index}) =>
<View className={'itemWrap'}>
<Item item={item} index={index} key={index} />
...
</View>
}
scrollY
keyExtractor = {(item,index) => `${index}`}
onScrollToUpper={this.onScrollToUpper.bind(this)}
onScrollToLower={this.onScrollToLower.bind(this)}
/>
2.4 视频封面和播放按钮
背景封面使用View相对定位+Image绝对定位实现
播放按钮居中利用一个和封面一样大小的透明蒙层作为容器,设置flex布局并设置内部子标签的垂直水平居中来实现
三 数据流
3.1 关注和取消关注
将mobx的数据模型注入到Item组件,以便于操作数据:
@inject('indexMod')
@observer
export default class Item extends PureComponent
点击关注或者已关注按钮时,调用mobx数据模型中的方法,修改数据
onFollowClick(index,active,name) {
const {indexMod} = this.props
indexMod.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.props
indexMod.currentId = tab.id
//判断当前tab的列表数据是否被缓存过
let hasCached = false
indexMod.list.map(data => {
if(data.id === tab.id){
hasCached = true
}
})
//如果没有缓存当前tab数据,就去请求服务器
if(!hasCached){
indexMod.getDatas(tab.id)
}
indexMod.onTabClick(tab.id)
}