一次基于Taro的曝光逻辑踩坑记录
事件起因
由于需求迭代,在详情页增加了热门/相似职位推荐列表,为了进一步确认推荐列表对职位的效果提升,增加曝光埋点统计处理,一切从数据出发。
实现方案
由于之前做过 H5 端的埋点上报,自然而然想到了通过 IntersectionObserver 进行监听的方式来实现。至于老旧的滚动监听就不再赘述了,想必实在没办法的情况下才会去考虑[旺柴]。
IntersectionObserver
首先我们需要创建一个 IntersectionObserver Taro.createIntersectionObserver(Object component, Object options)
,IntersectionObserver 一共有四个方法
- IntersectionObserver.relativeTo 使用选择器指定一个节点,作为参照区域之一。
- IntersectionObserver.relativeToViewport(Object margins) 指定页面显示区域作为参照区域之一
- IntersectionObserver.observeCallback callback) 指定目标节点并开始监听相交状态变化情况
- IntersectionObserver.disconnect() 停止监听。回调函数将不再触发
开发实现
通过在 JobItem 组件中进行监听来实现每个职位曝光逻辑,简要代码如下:
1 |
|
逻辑开发完之后在详情页观察推荐列表滚动曝光功能正常,心里美滋滋的想“Nice!”。
踩坑开始
由于推荐列表职位组件是复用首页列表的职位组件,所以想着给首页也增加上曝光逻辑,一次性补充完整。按照详情页逻辑追加相关处理后,简单看了下曝光触发没有问题,以为就这样顺利完工了。
由于曝光上报需要将每个职位在列表中的位置进行数据上报,所以额外留心了下位置数据是否正确,结果发现,首页中每个分页更新后,新分页的头部几个职位居然没有上报,出现了漏报的现象。
瞒报漏报是要承担责任的!!! 😈😈😈
分析问题
通过和详情页对比,发现可能是由于首页组件层级引起的。现有的首页由于之前做过性能优化,结合虚拟列表的思想,组件层级是按照 List 组件-Page 组件-Item 组件这个结构来设计的。先简单介绍下这个优化方案:
优化方案
通过对已有的长列表方案进行分析对比获知:
由于当时上述两个方案都和我们小程序的实际情况不是很贴合,所以自行结合虚拟列表的原理,设计了现有的优化方案:
这样就比常规方案里面把缓冲区外的 item 置成空的方案进一步减少了 Dom 结构。在这个方案里面,每个 Page 组件增加了 IntersectionObserver 监听,来更新当前分页与缓冲分页的页面编码。
找到原因
通过对组件 Page 层级组件的分析,怀疑是 Page 组件的监听事件优先级高于 Item 组件的监听事件,从而导致在更新分页时,新的分页的头部 Item 被分页的事件拦截了。
探寻解决方案
通过对 IntersectionObserver 相关资料的查找以及结合过往 H5 中的使用方法可以知道,其使用场景其实可以划分为两种:
- 组件内部:此时监听的是组件自身,在调用 createIntersectionObserver 进行创建是传入的第一个参数是自定义组件的 this;
- 小程序页面级(Page):此时可以监听一类组件元素,通过给需要监听的组件增加统一的类来实现监听。
那这样我们是不是可以给上面的 Page 组件和 Item 组件添加相同的监听类,来统一监听,就不会有事件优先级的问题了啊,说干就干,改造开始。
Round One
将 Page 组件和 Item 组件中的监听逻辑全部去掉,然后同步增加相关的 class ObserveItem
。在首页的页面文件中增加监听方法:
1 |
|
其中需要注意的是,在 Taro 开发小程序时,我们可以通过 getCurrentInstance()方法来获取页面的路由、实例等数据。通过查阅小程序的官方文档得知,在监听回调里面时可以返回一些有用的数据信息的:
这样我们就可以通过在监听组件上面通过data-* 的方式来保留一些数据用于进行区分和使用了。
理想很丰满,现实很骨感
监听发现,在 Taro 框架下,监听回调的参数里面 dataset 就是个{}
,明明小程序官方的例子是有的,结果,Taro 居然没有!!!
好的消息是,事件优先级的问题解决了 😂
Round Two
既然事件优先级这个核心问题解决了,那其他的我们只能绕绕路来实现了。通过对回调方法的数据分析得知,组件元素的 id 是可以获取到的。通过查阅 github 相关 issue 得知,可以通过 ref 获取到组件元素的 dataset 数据。
那我们只需要每个组件 id 对应上它的 ref 就可以在曝光的时候拿到我们需要的数据了。所以在每个组件的 Hooks 中追加了收集 ref 的方法调用
1 |
|
这样通过维护两个对象来存储每个监听元素对应的 ref,在曝光触发的回调中进行处理
1 |
|
踩坑回顾
其实这次需求处理是一个很常规的逻辑,只不过遇到了多级同类事件影响,以及框架封装能力和小程序官方不一致的情况,导致处理起来做了很多“迂回”处理。特此对这次问题的分析过程进行了本次汇总,希望能够帮助遇到同样问题的同学。如果您有更好的解决方案,也请留言告知,不胜感激!
- 本文作者:冷星
- 本文链接:http://lengxing.club/2022/06/01/%E4%B8%80%E6%AC%A1%E5%9F%BA%E4%BA%8ETaro%E7%9A%84%E6%9B%9D%E5%85%89%E9%80%BB%E8%BE%91%E8%B8%A9%E5%9D%91%E8%AE%B0%E5%BD%95/index.html
- 版权声明:本博客所有文章均采用 BY-NC-SA 许可协议,转载请注明出处!