關於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物件的網路請求流程
- 在後臺與伺服器交換資料,就會用到XMLHttpRequest物件
- 網路請求發生時,先回建立XMLHttpRequest物件即readyState = 0 也是呼叫open()方法
- 緊接著XMLHttpRequest物件呼叫send()方法,傳送客戶端網路請求,等待伺服器返回,即readyState的值為1 ,2,3的變化中(其中何時變化為何值可以參考下https://www.cnblogs.com/liujiale/p/5388110.html)
- 再次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 functions
XMLReq._requestID = id;
XMLReq._method = method;
XMLReq._url = url;
// 模擬XMLHttpRequest的onreadystatechange
let _onreadystatechange = XMLReq.onreadystatechange || function() {};
let onreadystatechange = function() {
let item = that.reqList[id] || {};
// update status
item.readyState = XMLReq.readyState;
item.status = 0;
if (XMLReq.readyState > 1) {
item.status = XMLReq.status;
}
item.responseType = XMLReq.responseType;
if (XMLReq.readyState == 0) {
// UNSENT
if (!item.startTime) {
item.startTime = (+new Date());
}
} else if (XMLReq.readyState == 1) {
// OPENED
if (!item.startTime) {
item.startTime = (+new Date());
}
} else if (XMLReq.readyState == 2) {
// HEADERS_RECEIVED
item.header = {};
let header = XMLReq.getAllResponseHeaders() || '',
headerArr = header.split("\n");
// extract plain text to key-value format
for (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) {
// DONE
clearInterval(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);
};
//覆蓋原始預設的onreadystatechange
XMLReq.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 data
if (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)
終於可來搞一搞日誌模組的原始碼了,其實程式碼都很簡單(哈哈哈),我開了一下git的日誌,想來我們現在看到的程式碼,都是之前迭代的程式碼,不是一開始,一個函式就很多行程式碼的,所以要理清條路,理解為什麼這樣加程式碼,當然能一開始就分清楚函式定義多少個,後面好加程式
vue中使用vconsole--移動端除錯神器
Vue中使用vconsole除錯手機移動端的點選事件 先使用npm install vconsole下載安裝依賴包 在Vue專案中新建 vconsole.js 檔案 ,在檔案中寫入 import Vconsole from 'vconsole' const vConsole = ne
vue---移動端除錯功能vConsole
一. 簡述 web端專案可以檢視瀏覽器控制檯資訊,方便除錯。然而移動端專案沒有控制檯可看,除錯起來特困難。最近在做基於vue框架的移動端專案,有的bug不看日誌,無法除錯,很頭疼。百度一下終於解決了這個難題,基於vue的有個可以在移動端檢視日誌的外掛vConsole,很好用
移動端除錯---vconsole
官方地址:https://www.npmjs.com/package/vconsole 使用方法: 1 本地呼叫 下載vconsole npm install vconsole 在專案中引入  
h5移動端除錯工具vConsole
1.npm使用方法 npm 安裝vconsole npm install vconsole -D 在 main.js 中引用 import Vconsole from 'vconsole'; const vConsole = new
移動端除錯工具--vConsole
Github地址:https://github.com/Tencent/vConsole平時Web端除錯時,我們一般習慣用console來讓控制檯輸出資訊,但是在移動端,我們無法再用console來觀察控制檯輸出的資訊,可以用alert代替console.log,但是aler
.NET Core 3.0之深入原始碼理解ObjectPool(一)
寫在前面 物件池是一種比較常用的提高系統性能的軟體設計模式,它維護了一系列相關物件列表的容器物件,這些物件可以隨時重複使用,物件池節省了頻繁建立物件的開銷。 它使用取用/歸還-重複取用的操作模式,如下圖所示: 本文將主要介紹物件池的基本概念、物件池的優勢及其工作機制,下一篇文件將從原始碼角度介紹.NET
.NET Core 3.0之深入原始碼理解ObjectPool(二)
寫在前面 前文主要介紹了ObjectPool的一些理論基礎,本文主要從原始碼角度理解Microsoft.Extensions.ObjectPool是如何實現的。下圖為其三大核心元件圖: 核心元件 ObjectPool ObjectPool是一個泛型抽象類,裡面只有兩個抽象方法,Get和Return。它從底
.NET Core 3.0之深入原始碼理解HealthCheck(一)
寫在前面 我們的系統可能因為正在部署、服務異常終止或者其他問題導致系統處於非健康狀態,這個時候我們需要知道系統的健康狀況,而健康檢查可以幫助我們快速確定系統是否處於正常狀態。一般情況下,我們會提供公開的HTTP介面,用於專門化健康檢查。 NET Core提供的健康檢查庫包括Microsoft.Extensio
.NET Core 3.1之深入原始碼理解HealthCheck(二)
寫在前面前文討論了HealthCheck的理論部分,本文將討論有關HealthCheck的應用內容。可以監視記憶體、磁碟和其他物理伺服器資源的使用情況來了解是否處於正常狀態。執行狀況檢查可以測試應用的依賴項(如資料庫和外部服務終結點)以確認是否可用和正常工作。執行狀況探測可以由容器業務流程協調程式和負載均衡器
控制容器文字行數(pc和 移動端)
phone 行數 spa pre size 以及 :hover 框架 mx4 寫在前面的話: 對於文字的單行以及多行顯示,應該是經常用到的一個功能了,看下文吧~ pc 端: 1. 單行限制(兼容所有瀏覽器) 這裏加了一個 鼠標移入時顯示全部 的效果:
各主流瀏覽器(PC、移動端)userAgent屬性信息
ble 信息 ie 8 瀏覽器版本 實用 link row inux oppo PC: IE、QQ、chrome、firefox、360、safair 移動端:微信內置瀏覽器、QQ、獵豹、百度、UC、2345、系統自帶 PC: ie: Mozilla/5
學習資料分享(Java第一行代碼視頻)<susmote.com>
pos medium 面向 學習 資料 java培訓 href 網盤 高級 17年買了一本書,第一行代碼(JAVA),李興華編寫的。 一開始我是按照書本一頁一頁的啃,一個點一個點的去學,雖然當時學的有些枯燥,但裏面的知識點大部分還是弄的懂,只是一次偶然,因為有點質疑書上寫
JS - 各瀏覽器對ES2015/ES6的支援情況(桌面端、移動端、以及伺服器)
2015年6月, ES2015(即 ECMAScript 6、ES6) 正式釋出。ES2015 是該語言的一個顯著更新,也是自 2009年 ES5 標準確定後的第一個重大更新。 ES6 提供了許多新特性,但並不是所有的瀏覽器都能夠完美支
eruda.js 移動端除錯神器使用教程(eruda)
在日常的移動端開發時,一般都是試用chrome瀏覽器的移動端模式進行開發和除錯,只有在chrome除錯完成,沒有問題了才會上到真機測試,移動端開發的一大問題就在於此, 各種品牌各種型號手機,手機中各種型別的瀏覽器APP........還好移動端的相對一致點,但是往往都會有一些各種各
Redis基本使用及百億數據量中的使用技巧分享(附視頻地址及觀看指南)
轉換 拆分 cache 避免 new 解決方案 pipe 收回 實例部署 作者:依樂祝原文地址:https://www.cnblogs.com/yilezhu/p/9941208.html 主講人:大石頭 時間:2018-11-10 晚上20:00 地
深入理解jvm(二、常用的垃圾收集器)
1.Serial 單執行緒收集器,它在進行垃圾收集時必須暫停其他工作執行緒,直到收集結束。是虛擬機器執行在客戶端下的預設新生代收集器。 相對於其他收集器的單執行緒來說,簡單高效。 2.ParNew 相當於Serial收集器的多執行緒版本,一般是執行在服務端的虛擬機器首選的新生代收集器
深入理解jvm(三、常用的垃圾收集規則)
1.物件優先在Eden分配 Eden Space字面意思是伊甸園,物件被建立的時候首先放到這個區域,進行垃圾回收後,不能被回收的物件被放入到空的survivor區域。 Survivor Space倖存者區,用於儲存在eden space記憶體區域中經過垃圾回收後沒有被回收的物件。Surviv
利用js自動檢測pc端和移動端,js程式碼,需要寫兩個網頁,一個pc,一個移動端
假設pc/index.html是pc端的網頁,mobile/index.html是移動端的網頁 在外部設定一個html進行判斷,分別跳轉; //判斷如果是pc端,自動跳到pc/index.html //安卓手機自動跳到mobile/
java使用itext操作填充pdf模板,(根據一個模板生成多頁資料)
直接開始需要兩個jar包 itext-asian-5.2.0.jar和 itextpdf-5.5.6.jar ,我的業務邏輯可能比較複雜,在這裡我就簡單的提供一個demo ,需要的人自己按照自己的業務邏輯來改。 首先我們要用 Adobe Acrobat 來編輯p