本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
上篇文章简单介绍了rrweb是如何进行事件监听以及如何处理节点变化内容,现在再回过头来思考一下我们的需求,我们需要还原展示页面的变化。
之前提到节点变化包含节点新增、节点移动、节点删除,以新增为例,我们在进行还原的时候需要知道在哪新增以及新增的内容是什么,这就涉及到节点的查找定位以及对节点内容进行处理,我们称之为序列化DOM。
那么在rrweb中是如何处理的呢,下面进行简单的介绍。
序列化DOM
节点的查找定位
不妨思考一下,我们要定位一个新增的节点,那么我们需要知道什么?
我们只需要知道它的父节点和兄弟节点,就可以定位到这个节点的位置。为了方便查找,rrweb在序列化节点时为每个节点都用id进行标识,通过id和DOM建立映射关系,这样在回放的时候就能很方便找到对应的DOM节点。
详细的代码可以查看rrweb-snapshot/src/snapshot.ts
节点内容处理
前面我们已经获取到了变化的节点,也能够定位它的位置,那为什么还要对节点内容进行处理呢?
- 有些页面元素我们并不需要记录,那么我们可以在序列化的时候进行处理,这里通过检查元素是否包含
blockClass类名或者是否匹配blockSelector选择器来判断元素是否需要被隐藏
- 有些页面的引用资源使用的是相对路径,那么我们就要遍历元素的atteributes属性,调用
transformAttribute方法处理成绝对路径
- 我们需要还原页面的样式,那么对于css中引用的资源也需要转换成绝对路径;还需要将外链style文件读取出来,拼接成字符串放到_cssText属性中
- 对于用户的输入数据,我们需要进行加密处理,这里调用
maskInputValue进行处理
- 页面canvas,目前对于canvas的处理方法为将其转换成base64图片保存
-
我们还可能需要对图片、视频、音频等媒体资源进行处理,可能页面中还会有iframe,rrweb-snapshot其实对这些都进行了处理
详细的代码可以查看rrweb-snapshot/src/snapshot.ts
经过上述的处理就实现了对DOM的序列化,在完成序列化之后还会调用wrapEvent给事件添加时间戳,这样回放的时候就能确定变化的先后顺序。
自此我们就获取了快照,到这里rrweb已经帮我们实现好了,我们只需要参照官网案例的调用方法调用即可。获取到快照之后,我们需要将这些快照发送到服务器保存以便后续调取回放,其实这里才是我们主要实现的内容,其实就是对回溯快照的管理功能,这里的很多思考其实和埋点的处理相似。
就暂且写到这里,后续随缘更新~
相关材料:
写在最后
写作不易,点个赞好不好~
关于我(资深划水,顶级潜水员,不定期更新,写啥随意)