onViewableItemsChanged简介
FlatList是React Native提供的一个高性能的列表组件,本身具备了列表Item缓存复用的逻辑,并且还支持下拉刷新等功能。在列表开发中,特别是FlatList列表滚动时,需要监听当前那些数据item在可见范围内,这时候就需要用到FlatList的onViewableItemsChanged属性。使用onViewableItemsChanged要与viewabilityConfig绑定使用。
- onViewableItemsChanged:在可见行元素变化时调用。
- viewabilityconfig:可见范围和变化频率等参数的配置。
viewabilityconfig常用的配置有如下一些:
如果不配置viewabilityconfig,viewabilityconfig是有一些默认属性值的。
示例
在左右分类的列表中,我们将向你展示如何onViewableItemsChanged实现可见列表的刷新,效果如下图所示。
首先,我们使用已经封装好的Axios工具执行数据请求,当然也可以直接使用Fetch工具进行请求,请求方法和参数如下:
async function getGoodCategory() {
let url = '/product/good/list-all'
let param = {
facilityCd: 188,
prodCatalogCd: 1201,
showInSelect: '1',
};
const data = await apiRequest.post(url,param)
.... //省略其他代码
}
复制代码
按照左右列表的特性,我们需要的数据结构是一个列表嵌套列表的结构,形如:
{
"data": {
"content": [
{
"id": "SC_188_5",
"productCategoryId": "GOOD_0",
"categoryName": "人气热销",
"categoryImageUrl": "/img/CGV_CMS_1609772871639.png",
"goodList": [
{
"id": "G_188_935",
"productCd": 22318,
"productId": "22010322",
"productName": "PAC虎年拜年礼包5",
"smallImageUrl": "/img/CGV_CMS_1643181892747.jpg",
"detailScreen": "PACONNIE虎年拜年礼包",
"productCategoryId": "GOOD_0",
"categoryName": "人气热销",
"price": 88.80,
"priceWithTax": 106.00,
"guidePrice": 88.80,
}
]
}
],
"totalElements": 6
},
"code": 200,
"message": "OK"
}
复制代码
拿到数据后,接下来就是绘制界面,分为左侧的分类列表和右侧的商品列表,核心代码如下:
const GoodListScreen = ({navigation: {navigate}}) => {
let currentCategoryName
const sectionListEle = useRef(null)
const [goods, setGoods] = useState([])
const [selectedIndex, setSelectedIndex] = useState(0)
useEffect(() => {
getGoodCategory()
}, [])
async function getGoodCategory() {
let url = '/product/good/list-all'
let param = {
facilityCd: 188,
prodCatalogCd: 1201,
showInSelect: '1',
};
const data = await apiRequest.post(url,param)
setGoods(
(data.content).map(({goodList, ...res}, index) => ({
...res,
isHot: index === 0,
data: goodList,
})),
)
}
const select = (index) => {
if (selectedIndex !== index) {
setSelectedIndex(index)
sectionListEle.current.scrollToLocation({
animated: false,
itemIndex: 0,
sectionIndex: index,
viewPosition: 0,
})
}
}
const onViewableItemsChanged = (info) => {
const fisrtViewableItem = info.viewableItems[0]
if (fisrtViewableItem) {
const {categoryName} = fisrtViewableItem.item
if (categoryName !== currentCategoryName) {
const index = goods.findIndex((c) => c.categoryName === categoryName)
setSelectedIndex(index)
currentCategoryName = categoryName
}
}
}
const createGoodOrder = async () => {
}
function renderShopCart() {
return (<ShoppingCartBar
style={{height:60}}
amount={0}
num={0}
onPressLeft={() => navigate('MyModal', {screen: 'ShopingCartScreen'})}
onPressRight={() => {
createGoodOrder()
}}
/>);
}
function renderLeftList() {
return (<View style={styles.leftList}>
<FlatList
data={goods}
renderItem={({item, index}) => (
<Menu
item={item}
isHot={index === 0}
isSelected={index === selectedIndex}
select={() => select(index)}
/>
)}
keyExtractor={(item) => item.id}
/>
</View>);
}
function renderRightList() {
return (<SectionList
style={styles.rightList}
ref={sectionListEle}
onScrollToIndexFailed={() => ({
index: selectedIndex,
highestMeasuredFrameIndex: 0,
averageItemLength: 100,
})}
sections={goods}
renderItem={({item}) => (
<GoodItem item={item}/>
)}
keyExtractor={(item) => item.id}
onViewableItemsChanged={onViewableItemsChanged}
/>);
}
return goods.length>0 && (
<View style={styles.contain}>
<View style={styles.body}>
{renderLeftList()}
{renderRightList()}
</View>
{renderShopCart()}
</View>
)
}
const styles = StyleSheet.create({
contain: {
flexDirection:'column',
flex:1
},
body: {
flex: 1,
flexDirection: 'row',
},
leftList: {
width: 72,
backgroundColor: '#FBF8FB',
},
rightList: {
flex: 1,
},
title: {
backgroundColor: '#fff',
padding: 5,
},
})
export default GoodListScreen;
复制代码
上面代码最核心的代码是使用了FlatList组件的onViewableItemsChanged实现右侧列表的变化监听,核心代码为:
const onViewableItemsChanged = (info) => {
const firstViewableItem = info.viewableItems[0]
if (firstViewableItem) {
const {categoryName} = firstViewableItem.item
if (categoryName !== currentCategoryName) {
const index = goods.findIndex((c) => c.categoryName === categoryName)
setSelectedIndex(index)
currentCategoryName = categoryName
}
}
}
复制代码
当点击左侧的分类列表时,我们会调用Menu组件动的select属性,执行select方法,由于右侧的列表使用了onViewableItemsChanged属性,当收到刷新的通知后就会自动刷新界面。而为了实现滑动右侧的列表,左侧的列表也能够滑动,在onViewableItemsChanged方法中,我们增加了如下的逻辑。
if (categoryName !== currentCategoryName) {
const index = goods.findIndex((c) => c.categoryName === categoryName)
setSelectedIndex(index)
}
复制代码
到此,左右列表联动的功能就实现了。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END