hugh 的个人博客

vuePress-theme-reco hugh 的个人博客    2021
hugh 的个人博客

Choose mode

  • dark
  • auto
  • light
Home
分类
  • 前端
  • fe-robot
  • 前端监控
标签
专题
  • femonitor
  • jsby
  • fe-robot
TimeLine
工具
全版

hugh 的个人博客

154

Article

324

Tag

Home
分类
  • 前端
  • fe-robot
  • 前端监控
标签
专题
  • femonitor
  • jsby
  • fe-robot
TimeLine
工具
全版
  • 数据收集篇

  • 数据分析篇

  • 数据监控篇

  • 采坑篇

    • 奇怪的input_-前端监控之采坑篇
      • 大坑描述
      • 问题分析
      • 解决方案
    • comment类型的节点引发的还原布局错误-前端监控之采坑篇
      • 大坑描述
      • 问题分析
      • 问题解决
    • 利用外部mq中间件解决单实例的简单消息队列重启丢失的问题
      • 1. 解决node中耗时操作对请求的影响
      • 问题
      • 解决
    • mapreduce使用的坑-mac_reduce对数据集进行汇总计算时,出现数据样本不全的问题
      • 1. mapreduce
      • 2. 问题案例
      • 3. 原因
      • 4. 解决方案

奇怪的input_-前端监控之采坑篇

vuePress-theme-reco hugh 的个人博客    2021

奇怪的input_-前端监控之采坑篇


hugh 的个人博客 2019-11-28 12:30:23 前端监控webfe_monitor前端

# 大坑描述

在录屏收集时, 对于部分js设置的输入框值无法获取到,但是该元素确实已加入mutation监控。

# 问题分析

input mutation demo

demo中可以看出

  1. input 输入框,对于不同的type, 在数据变更时,浏览器的操作是不同的 191128input.gif

  2. 对于input 隐藏域, 无论操作的是attr还是展示value,都会反应到value属性上

  3. radio或checkbox类型,手动点击选择不会触发mutation监听

  4. textarea的效果和input普通输入框一致

# 解决方案

利用Object.defineProperty 修改原对象value(checked)属性的set方法, 手动监听 这边涉及到的输入Element对象如下 HTMLInputElement, HTMLSelectElement, HTMLTextAreaElement

修改绑定代码如下:

function wrapInput(reporter) {
        function wrap(e, r) {
          var i = Object.getOwnPropertyDescriptor(e.prototype, r);
          return Object.defineProperty(e.prototype, r, {
            set: function set(e) {
              var node = this, n = mirrorNode.getId(node);
              if(n) {
                // 取该node的上一个属性值
                var last = elementMap[n];
                if(!last || (r === 'value' && last.text != e) || (r === 'checked' && last.isChecked != e)) {
                 // setTimeout的作用,用于延迟执行,便于将新属性值写入缓存
                  setTimeout(function() {
                   // 用于触发change方法
                    eventDoMap("change", reporter)({target: node, type: "change"})
                  })
                }
              }
              return i.set.call(this, e);
            }, get: function get() {
              return i.get.call(this);
            }
          }), /**该方法定义了还原方法**/function () {
            return Object.defineProperty(e.prototype, r, i);
          };
        }

        var p = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value"),
            f = [];
        p && p.set && (f = f.concat([wrap(HTMLInputElement, "value"), wrap(HTMLInputElement, "checked"), wrap(HTMLSelectElement, "value"), wrap(HTMLTextAreaElement, "value")]));

        return function () {
           // 此处用于还原重写
          f.forEach(function (e) {
            return e();
          });
        };
      }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37