携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情
前言
列表曝光是一个常用功能,在H5中可以使用 IntersectionObserver
:
var observer = new IntersectionObserver(callback[, options]);
其中 callback
是触发条件时的回调函数。 options
则是一个配置对象,具体的 api 使用可以查看 MDN。
React Native 也有封装了类似的功能,我们一起来看下。
FlatList
该组件是ReactNative提供的一个组件,用于加载列表,并支持上拉加载等功能,其中有一个功能 onViewableItemsChanged
支持在可见行元素变化时调用。可见范围和变化频率等参数的配置需设置viewabilityConfig
属性,使用时代码如下:
// 封装一个FlatList组件
//列表滚动变化监听配置
const VIEWABILITY_CONFIG = {
minimumViewTime: 3000, // 节流的时间间隔
viewAreaCoveragePercentThreshold: 10, // 0 - 100 表示新的内容出现占比多少时触发,100表示需完整出现,-0递减
waitForInteraction: false, // 是否第一次出现内容的时候就触发
};
const SuperFlatList = props => {
const viewConfigRef = useRef(VIEWABILITY_CONFIG)
const ononViewableItemsChangedRef = useRef(_onViewableItemsChanged)
// 列表滚动时会触发这个回调函数
const _onViewableItemsChanged = changed => {
console.log('曝光', changed)
}
return (<FlatList
viewabilityConfig={viewConfigRef.current}
onViewableItemsChanged={ononViewableItemsChangedRef.current}
{...props}
/>
}
上面代码的 onViewableItemsChanged
是在列表内 Item
出现时的回调,此时我们已经可以获取到item的变化了,但是需求还要求我们不能重复的曝光。比如上下来回滑动时,单次搜索已经曝光的组件不再曝光,所以我们还需要写一个变量去存当前已经曝光过的item
// 当前正在显示的数组
const currentOnViewList = useRef([])
// 当前的已埋点的数组记录
const currentListIsTracked = useRef([])
// 用于检出changed中是显示的item
let getChangedListIsViewable = (arr) => {
if (!Array.isArray(arr)) return []
return arr.filter(item => item.isViewable)
}
// 埋点方法
const checkAndTrack = (listIsViewable) => {
listIsViewable.forEach((item) => {
// 如果currentOnViewList里面不包含在listIsViewable里,说明还未埋点,需要埋入
if (currentListIsTracked.current.filter(i => i.index === item.index).length === 0) {
// 一些操作
}
})
}
const _onViewableItemsChanged = changed => {
// deWeight 是一个根据对象key名去重对象数组方法,此处略过...
currentOnViewList.current = deWeight([...currentOnViewList.current, ...changed.viewableItems], 'index')
checkAndTrack(getChangedListIsViewable(changed.changed))
console.log('曝光', changed)
}
这样一个简单的曝光FlatList组件就完成了,我们也可以思考一些其他问题:
1,如果需要增加曝光的时间,应该如何去处理?时间分为停留时间,即item从屏幕出现到离开的时间
2,如果item数据是嵌套时,应该如何去解析数据?