关于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

相关文章

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

高效录音转文字:2024年四大工具精选!

在快节奏的工作生活中,能够快速将录音转换成文字是一项非常实用的能力。特别是在需要记录会议纪要、讲座内容或者是采访素材的时候,一款优秀的在线录音转文字工具能派上大用场。以下推荐几个好用的录音转文字工具! 365在线转文字 直达链接:https://www.pdf365.cn/ 365在线转文字是一款提供在线录音转文字服务的工具,它以其高效、便捷的特点受到用户的青睐。用户无需下载安装任何软件,只

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get