$0 和 __vue__
$0 是指當滑鼠點選 Element 皮膚的某個 dom 元素後,console 裡 $0 變數會自動指向該 dom 元素物件
__vue__ 是指 vue 框架會往 vue 元件 $mount 掛載的 dom 元素物件上新增一個 __vue__
變數來指向當前 vue 元件
這意味我們可以直接在 console 皮膚裡拿到任意 vue 元件例項物件:
- 可以檢視物件內部任意屬性
- 也可以直接操作物件內部的屬性來達到預期的除錯效果
- 甚至可以用來檢視三方庫的 api,比如 element-ui 的某個元件內部的 api
或許你會疑問,這不是安裝 chrome 外掛(vue devtools)就可以搞定的事嗎,外掛還是個視覺化介面操作,更直觀便捷
沒錯!外掛當然更方便,但沒準外掛內部實現原理就是這樣的呢,掌握這個技巧,也可以在一些外掛無法覆蓋的場景下來除錯頁面,比如:
- 生產環境的頁面
- 內網部署且無法代理到本地的頁面
- 非 chrome 瀏覽器
- 等等
舉一反三:
- 很多開源庫框架其實都會往繫結的 dom 或者 window 上掛載一些變數上去,善於在 console 利用這些變數,可以方便我們進行很多非本地開發場景下的除錯
- 我們日常封裝一些複雜業務、複雜元件時,也可以參考這種思路,給自己開一個非本地開發場景下的除錯入口,但注意別記憶體洩漏了
- window 上掛例項物件變數容易導致記憶體洩漏,所以建議掛一些全域性作用域的物件;例項物件儘量掛與他生命週期繫結的 dom 物件
介面資料搜尋定位
網路皮膚支援多個維度的搜尋功能:
- 根據內容關鍵詞定位介面
- 常用於看見介面某個文案或者只知道某個關鍵詞,但想定位它是哪個介面返回時的場景
- 在介面返回的內容裡定位關鍵詞
- 根據 url 過濾介面
原始碼定位
jquery 時代的網頁原始碼直接原原本本在瀏覽器上,除錯和閱讀都非常方便;
前端工程化後,混淆和壓縮已經是標配,當出現生產故障時,首先考慮的應該是本地復現或者是將生成環境頁面代理至本地的思路來解決;
但總會有某些場景,由於各種受限,只剩下瀏覽器直接操作的手段,因此,掌握一些原始碼定位和除錯的方式技巧還是有必要的
全域性搜尋
字串、物件屬性欄位名這些不會被混淆,可以藉助這類場景的關鍵詞來搜尋定位原始碼位置
通常介面也是第一看到的東西,儘量找個介面上看著不像通用類的文案全域性搜尋下,基本都能定位到對應元件原始碼
也可以審查元素,在 Element 皮膚裡找到對應 dom 上比較唯一的 class 或 id 等來全域性搜尋
介面呼叫棧
介面也是邏輯分析的入口點之一,比如找到某個頁面呈現資料的請求介面,跟著呼叫棧走下去基本能梳理介面從拿到資料到呈現做了什麼事
但要注意過濾掉三方庫(如 axios, vue 等)對介面的封裝,找到真實屬於邏輯原始碼的呼叫棧
console 皮膚的函式原始碼跳轉
console 皮膚上的 log 日誌,或者透過 log 輸出一個函式,都支援點選跳轉到對應原始碼位置
藉助 $0 和 __vue__
變數,找到對應元件的某個方法入口,透過 log 輸出方法再跳轉至原始碼位置,就能針對性的梳理某個邏輯原始碼
事件監聽事件跳轉
對於某些按鈕等元件的點選之類的事件,可以直接透過審查元素的 Element 皮膚的 EventListeners(事件監聽器)這邊檢視到該按鈕各類事件的監聽器
過濾掉三方庫的統一事件監聽器,找到自己邏輯原始碼的事件監聽器入口,也能針對性梳理該事件處理邏輯原始碼
原始碼除錯
斷點
程式碼里加入 debugger 可以觸發斷點,但前提是本地開發除錯模式
也可以直接瀏覽器上操作斷點,除了常規的直接點選原始碼斷點之外,也可以使用一些具體場景的斷點,比如定時器觸發時進入斷點、非同步請求響應時斷點,DOM 變更時斷點等等
overrides(覆蓋)
如果想在瀏覽器上修改原始碼並生效的話,需要使用到 overrides(覆蓋|替換)功能,如上圖
先在 Source(原始碼/來源) 皮膚啟用 overrides(替換) 功能,然後找到要編輯的原始碼檔案,右鍵,點選替換內容(Save for override)
接下去就可以直接瀏覽器上修改原始碼,重新整理後會載入這份修改後的程式碼檔案
當你發現網路皮膚有個感汗號警告時,就意味著你啟用了本地替換的功能,指定的原始碼檔案不會從網路上載入,而是載入本地臨時替換修改過的檔案
這樣就可以達到直接在原始碼除錯的效果
實操場景說明
以上是個人日常比較常用的一些操作,每個技巧都不是割裂開的,經常是組合交叉使用
比如某生產環境來了個故障,本地無法復現,無法代理,還是個內網,只能遠端客戶裝置直接在瀏覽器介面上除錯定位
首先,我們要定位到大概原始碼,然後分析、斷點、除錯
怎麼定位原始碼呢:
- 字串是不會被混淆的,所以可以全域性搜尋方式來嘗試
- 如果匹配點太多,那也可以先定位到某個關鍵介面,然後根據介面定位到原始碼
- 如果還是沒有定位到,物件的屬性是不會被混淆的,所以也可以透過
$0 和 __vue__
來根據某個 vue 元件的方法來定位原始碼
定位到原始碼後,斷點還分析不出問題時,就可以繼續利用 overrides
覆蓋功能來直接修改瀏覽器原始碼進行除錯