React Native 列表组件曝光功能实现

971 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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数据是嵌套时,应该如何去解析数据?