关于vConsole 源码的理解分享(vConsole一个移动端调试控制台工具)(2)

2023-12-20 01:58

本文主要是介绍关于vConsole 源码的理解分享(vConsole一个移动端调试控制台工具)(2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

终于可来搞一搞日志模块的源码了,其实代码都很简单(哈哈哈),我开了一下git的日志,想来我们现在看到的代码,都是之前迭代的代码,不是一开始,一个函数就很多行代码的,所以要理清条路,理解为什么这样加代码,当然能一开始就分清楚函数定义多少个,后面好加代码,扩展的 这个思路架构也是我们要瞻仰,学习的。
log这个模块的类图结构知道,它在VConsolePlugin上又封装了一层,类图结构件上一篇文章上一篇文章
即VConsoleLogTab 作为一个log模块基础的类结构
废话不多说直接贴代码看实现,代码才是王道

什么构造函数和初始化就不说了,直接来看怎么替代js浏览器对象的打印

/*** replace window.console with vConsole method* @private*/mockConsole() {const that = this;const methodList = ['log', 'info', 'warn', 'debug', 'error'];if (!window.console) {window.console = {};} else {methodList.map(function(method) {that.console[method] = window.console[method];});that.console.time = window.console.time;that.console.timeEnd = window.console.timeEnd;that.console.clear = window.console.clear;}methodList.map(method => {window.console[method] = (...args) => {this.printLog({logType: method,logs: args});};});const timeLog = {}window.console.time = function(label) {timeLog[label] = Date.now();};window.console.timeEnd = function(label) {var pre = timeLog[label];if (pre) {console.log(label + ':', (Date.now() - pre) + 'ms');delete timeLog[label];} else {console.log(label + ': 0ms');}};window.console.clear = (...args) => {that.clearLog();that.console.clear.apply(window.console, args);};}

该方法就是模拟console对象

  • 判断window的console对象是否存在
  • 如果不存在就让console = {},for循环自己实现,console的erron,log等方法,
  • 如果存在,劫持console.log的各个方法,将方法保存在that对象中,其实我也不知道这个是个什么意思,我觉得这个劫持可以不要,反正你后面都是全部自己实现了log,error,warn,clear,time,timeEnd,等方法,不知道作者这里是个什么意思

这样差不多log模块毕,接下来看看network,这里就不卖关子了,其实网络请求也是通过类似于日志模块模拟ajax的方式。

在此之前,来梳理下window.XMLHttpRequest对象的网络请求流程

  1. 在后台与服务器交换数据,就会用到XMLHttpRequest对象
  2. 网络请求发生时,先回创建XMLHttpRequest对象即readyState = 0 也是调用open()方法
  3. 紧接着XMLHttpRequest对象调用send()方法,发送客户端网络请求,等待服务器返回,即readyState的值为1 ,2,3的变化中(其中何时变化为何值可以参考下https://www.cnblogs.com/liujiale/p/5388110.html)
  4. 再次XMLHttpRequest等待服务器响应完毕,readyState为4
    注意这个onreadystatechange这个事件很重要,每当readyState值变化是都会触发这个方法,在这个方法我们就可以取用XMLHttpRequest对象的一些有用的属性值来做文章了比如responseText,status等
    所以了解了这个过程,在来看下面的代码就很简单,说白了就是重写了send,open,onreadystatechange等方法
  /*** mock ajax request* @private*/mockAjax() {let _XMLHttpRequest = window.XMLHttpRequest;if (!_XMLHttpRequest) { return; }//将this存储起来let that = this;let _open = window.XMLHttpRequest.prototype.open,_send = window.XMLHttpRequest.prototype.send;that._open = _open;that._send = _send;// 模拟XMLHttpRequest的open方法window.XMLHttpRequest.prototype.open = function() {let XMLReq = this;//分割请求的参数let args = [].slice.call(arguments),method = args[0],url = args[1],id = that.getUniqueID(); //设置一个值存储当前请求的唯一id,唯一标识//定义一个时间计时器let timer = null;// may be used by other functionsXMLReq._requestID = id;XMLReq._method = method;XMLReq._url = url;//  模拟XMLHttpRequest的onreadystatechangelet _onreadystatechange = XMLReq.onreadystatechange || function() {};let onreadystatechange = function() {let item = that.reqList[id] || {};// update statusitem.readyState = XMLReq.readyState;item.status = 0;if (XMLReq.readyState > 1) {item.status = XMLReq.status;}item.responseType = XMLReq.responseType;if (XMLReq.readyState == 0) {// UNSENTif (!item.startTime) {item.startTime = (+new Date());}} else if (XMLReq.readyState == 1) {// OPENEDif (!item.startTime) {item.startTime = (+new Date());}} else if (XMLReq.readyState == 2) {// HEADERS_RECEIVEDitem.header = {};let header = XMLReq.getAllResponseHeaders() || '',headerArr = header.split("\n");// extract plain text to key-value formatfor (let i = 0; i < headerArr.length; i++) {let line = headerArr[i];if (!line) { continue; }let arr = line.split(': ');let key = arr[0],value = arr.slice(1).join(': ');item.header[key] = value;}} else if (XMLReq.readyState == 3) {// LOADING} else if (XMLReq.readyState == 4) {// DONEclearInterval(timer);item.endTime = +new Date(),item.costTime = item.endTime - (item.startTime || item.endTime);item.response = XMLReq.response;} else {clearInterval(timer);}if (!XMLReq._noVConsole) {that.updateRequest(id, item);}return _onreadystatechange.apply(XMLReq, arguments);};//覆盖原始默认的onreadystatechangeXMLReq.onreadystatechange = onreadystatechange;//为了怕请求过程占用第三方应用汇修改xhr默认的方法,所以用了一个定时器循环来监听readyState的变化let preState = -1;timer = setInterval(function() {if (preState != XMLReq.readyState) {preState = XMLReq.readyState;onreadystatechange.call(XMLReq);}}, 10);return _open.apply(XMLReq, args);};// 默认send方法window.XMLHttpRequest.prototype.send = function() {let XMLReq = this;let args = [].slice.call(arguments),data = args[0];//重请求池找出相应的请求let item = that.reqList[XMLReq._requestID] || {};item.method = XMLReq._method.toUpperCase();//处理url后面跟着的参数,//1,先以?分割为数组let query = XMLReq._url.split('?'); // a.php?b=c&d=?e => ['a.php', 'b=c&d=', '?e']// 2,在去除最前面的数组item.url = query.shift(); // => ['b=c&d=', '?e']if (query.length > 0) {item.getData = {};//3,然后剩下的?又重新连接在一起query = query.join('?'); // => 'b=c&d=?e'//4,在以& 去键值对query = query.split('&'); // => ['b=c', 'd=?e']for (let q of query) {q = q.split('=');item.getData[q[0]] = q[1];}}//处理post请求方式,注意这里 会有url接参数,但又是post请求的情况,这里也能处理if (item.method == 'POST') {// save POST dataif (tool.isString(data)) {let arr = data.split('&');item.postData = {};for (let q of arr) {q = q.split('=');item.postData[q[0]] = q[1];}} else if (tool.isPlainObject(data)) {item.postData = data;}}if (!XMLReq._noVConsole) {that.updateRequest(XMLReq._requestID, item);}return _send.apply(XMLReq, args);};};

这个就比较底层了,其实也不是,只不过我们平时开发的时候,习惯用封装好的比如jq等,其实背后做了很多时候事情!

接下来是最后的存储模块,VConsole里主要是列了cookie和localStorage的存储
localStorage就不说了,贴心cookie的的代码

getCookieList() {if (!document.cookie || !navigator.cookieEnabled) {return [];}let list = [];let items = document.cookie.split(';');for (let i=0; i<items.length; i++) {let item = items[i].split('=');let name = item.shift().replace(/^ /, ''),value = item.join('=');list.push({name: decodeURIComponent(name),value: decodeURIComponent(value)});}return list;}

结束了,以上是个人见解,欢迎指正批评!谢谢

这篇关于关于vConsole 源码的理解分享(vConsole一个移动端调试控制台工具)(2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/514447

相关文章

Java数字转换工具类NumberUtil的使用

《Java数字转换工具类NumberUtil的使用》NumberUtil是一个功能强大的Java工具类,用于处理数字的各种操作,包括数值运算、格式化、随机数生成和数值判断,下面就来介绍一下Number... 目录一、NumberUtil类概述二、主要功能介绍1. 数值运算2. 格式化3. 数值判断4. 随机

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

MySQL8.2.0安装教程分享

《MySQL8.2.0安装教程分享》这篇文章详细介绍了如何在Windows系统上安装MySQL数据库软件,包括下载、安装、配置和设置环境变量的步骤... 目录mysql的安装图文1.python访问网址2javascript.点击3.进入Downloads向下滑动4.选择Community Server5.

CentOS系统Maven安装教程分享

《CentOS系统Maven安装教程分享》本文介绍了如何在CentOS系统中安装Maven,并提供了一个简单的实际应用案例,安装Maven需要先安装Java和设置环境变量,Maven可以自动管理项目的... 目录准备工作下载并安装Maven常见问题及解决方法实际应用案例总结Maven是一个流行的项目管理工具

Java中基于注解的代码生成工具MapStruct映射使用详解

《Java中基于注解的代码生成工具MapStruct映射使用详解》MapStruct作为一个基于注解的代码生成工具,为我们提供了一种更加优雅、高效的解决方案,本文主要为大家介绍了它的具体使用,感兴趣... 目录介绍优缺点优点缺点核心注解及详细使用语法说明@Mapper@Mapping@Mappings@Co

10个Python自动化办公的脚本分享

《10个Python自动化办公的脚本分享》在日常办公中,我们常常会被繁琐、重复的任务占据大量时间,本文为大家分享了10个实用的Python自动化办公案例及源码,希望对大家有所帮助... 目录1. 批量处理 Excel 文件2. 自动发送邮件3. 批量重命名文件4. 数据清洗5. 生成 PPT6. 自动化测试

使用Python实现图片和base64转换工具

《使用Python实现图片和base64转换工具》这篇文章主要为大家详细介绍了如何使用Python中的base64模块编写一个工具,可以实现图片和Base64编码之间的转换,感兴趣的小伙伴可以了解下... 简介使用python的base64模块来实现图片和Base64编码之间的转换。可以将图片转换为Bas

使用Java实现一个解析CURL脚本小工具

《使用Java实现一个解析CURL脚本小工具》文章介绍了如何使用Java实现一个解析CURL脚本的工具,该工具可以将CURL脚本中的Header解析为KVMap结构,获取URL路径、请求类型,解析UR... 目录使用示例实现原理具体实现CurlParserUtilCurlEntityICurlHandler

10个Python Excel自动化脚本分享

《10个PythonExcel自动化脚本分享》在数据处理和分析的过程中,Excel文件是我们日常工作中常见的格式,本文将分享10个实用的Excel自动化脚本,希望可以帮助大家更轻松地掌握这些技能... 目录1. Excel单元格批量填充2. 设置行高与列宽3. 根据条件删除行4. 创建新的Excel工作表5