写过点啥-用rrweb实现了个回溯系统(三)-- rrweb的具体实现(2)

416 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

上篇文章简单介绍了rrweb是如何进行事件监听以及如何处理节点变化内容,现在再回过头来思考一下我们的需求,我们需要还原展示页面的变化。

之前提到节点变化包含节点新增、节点移动、节点删除,以新增为例,我们在进行还原的时候需要知道在哪新增以及新增的内容是什么,这就涉及到节点的查找定位以及对节点内容进行处理,我们称之为序列化DOM。

那么在rrweb中是如何处理的呢,下面进行简单的介绍。

序列化DOM

节点的查找定位

不妨思考一下,我们要定位一个新增的节点,那么我们需要知道什么?

我们只需要知道它的父节点和兄弟节点,就可以定位到这个节点的位置。为了方便查找,rrweb在序列化节点时为每个节点都用id进行标识,通过id和DOM建立映射关系,这样在回放的时候就能很方便找到对应的DOM节点。

image-20220809104239623.png

详细的代码可以查看rrweb-snapshot/src/snapshot.ts

节点内容处理

前面我们已经获取到了变化的节点,也能够定位它的位置,那为什么还要对节点内容进行处理呢?

  • 有些页面元素我们并不需要记录,那么我们可以在序列化的时候进行处理,这里通过检查元素是否包含blockClass类名或者是否匹配blockSelector选择器来判断元素是否需要被隐藏

image-20220809154231717.png

  • 有些页面的引用资源使用的是相对路径,那么我们就要遍历元素的atteributes属性,调用transformAttribute方法处理成绝对路径

image-20220809152500462.png

  • 我们需要还原页面的样式,那么对于css中引用的资源也需要转换成绝对路径;还需要将外链style文件读取出来,拼接成字符串放到_cssText属性中

image-20220809153603774.png

  • 对于用户的输入数据,我们需要进行加密处理,这里调用maskInputValue进行处理

image-20220809153722238.png

  • 页面canvas,目前对于canvas的处理方法为将其转换成base64图片保存

image-20220809154645898.png

  • 我们还可能需要对图片、视频、音频等媒体资源进行处理,可能页面中还会有iframe,rrweb-snapshot其实对这些都进行了处理

    详细的代码可以查看rrweb-snapshot/src/snapshot.ts

经过上述的处理就实现了对DOM的序列化,在完成序列化之后还会调用wrapEvent给事件添加时间戳,这样回放的时候就能确定变化的先后顺序。

自此我们就获取了快照,到这里rrweb已经帮我们实现好了,我们只需要参照官网案例的调用方法调用即可。获取到快照之后,我们需要将这些快照发送到服务器保存以便后续调取回放,其实这里才是我们主要实现的内容,其实就是对回溯快照的管理功能,这里的很多思考其实和埋点的处理相似。

就暂且写到这里,后续随缘更新~

相关材料:

rrwebMutationObserver

写在最后

写作不易,点个赞好不好~

关于我(资深划水,顶级潜水员,不定期更新,写啥随意)