公司产品有个埋点需求,当用户在点击日志记录时,上报日志列表中最新记录和当前记录的信息,由于组件间距离比较远,没办法直接拿到多层之外组件中的数据,因此用了hack的办法解决,记录在此,以飨读者。
背景介绍
笔者正在参与的项目有一个日志记录中心功能,类似于上图所示的通知中心。产品给的需求如下:
用户点击某条记录时埋点 ——> 需要发送当前的记录类型及创建时间,及日志列表中最新记录的创建时间、最新记录与当前记录的间隔数。
在React中,数据主要是通过单向数据流向子组件传递,仔细分析后发现通过传统方式不好拿。
首先用户点击的记录没有最新记录的信息,所以也不会有最新记录的创建时间,其次,记录是懒加载,所以最新记录与当前记录之间的间隔数也没法直接拿。
如果通过重构的方式在组件中传递这些数据肯定是可以的,但是要花费很大的代价,且不说涉及到多层业务组件层层嵌套,就算是把数据放到Redux中存储,也需要花费比较多的计算资源,稍有不慎也会导致组件的非必要渲染。
这次使用的hack方式,技术原理并不复杂,核心思想是在页面中拿到DOM,并使用DOM节点的原生方法进行计算,得到想要的数据。
拿到最新记录的日志类型和时间戳
与标准html一致,在React中支持使用 data-* 属性来嵌入自定义数据:
<div className="item" data-time={item.time} onClick={this.handleClick}>
一个DIV节点
<div/>
比如在上面的div标签中,通过使用data-time属性,将当前记录的time字段绑定到了标签上。
绑定以后如何获取呢,同样可以使用浏览器的原生方法,如:document.getElementById()
document.querySelectorAll(),这里使用第二种方式演示:
//获取到日志记录DOM列表(每一条为一个DOM节点)
const itemList = document.querySelectorAll('.item')
//获取用户点击的DOM节点在list中的位置
const clickedRecord = [].indexOf.call(itemList, e.currentTarget)
//获取第一个DOM节点上绑定的time数据
const firstItemTime = itemList[0].getAttribute('data-time')
简述一下过程:通过日志item独有的className标签拿到日志记录的DOM列表,然后通过鼠标点击对象的currentTarget属性拿到当前点击的日志DOM对象,进而计算当前日志在列表中所处的位置。最新记录的创建时间通过DOM节点的getAttribute方法拿到绑定的数据。
总结
React官方并不推荐直接操作DOM,但直接操作DOM的确能解决很多特殊的业务需求(香啊),所以开发者朋友在闲来无事的时候还是要把DOM的方法捡起来,说不定啥时候就用上了。另外需要说明的是这只是一个临时的埋点需求,如果是项目中比较核心的功能点,采用这种方式还需要认真评估。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。