前端(vue)入門到精通課程,老師在線輔導:聯(lián)系老師
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API調(diào)試工具:點擊使用
在上一篇文章中,我們介紹了具體什么是變更檢測,用一個原生JS例子來更好的去理解變更檢測,以及介紹了在哪些場景下會觸發(fā)變更檢測。前文中總結(jié)了5種工作中常見的場景,但是我們需要先思考一下,Angular的變更檢測是否支持所有的異步事件呢?如果支持,可以列出來嗎?如果有些不支持,哪些不支持呢?這些問題會在后續(xù)文章中詳細的講解?!鞠嚓P(guān)教程推薦:《angular教程》】
如何訂閱異步事件
只要發(fā)生了異步操作,Angular就后進行變更檢測,那么Angular是如何訂閱(感知)到異步事件的呢?也就是說,當異步事件執(zhí)行的時候,Angular是怎么知道的呢?先來了解一下zone.js。
zone.js
zone.js 提供了一種稱為zone的機制,用于封裝和攔截瀏覽器中的異步任務(wù),還提供了異步生命周期鉤子和統(tǒng)一的異步錯誤處理機制。
zone.js是通過打補丁的方式來對瀏覽器中常見方法和元素進行攔截,比如setTimeout和HTMLElement.prototype.onclick。Angular在啟動時會利用zone.js修補幾個瀏覽器API,從而去實現(xiàn)異步事件的捕獲,并在捕獲事件后調(diào)用變更檢測。
package.json如下示例:
{ "dependencies": { ... "zone.js": "~0.10.2" } }
可以簡單來看一下zone.js。
比如,在Vue2中的數(shù)據(jù)響應(yīng)式,我們都知道它是使用了Object.defineProperty來實現(xiàn)數(shù)據(jù)變化的攔截,但是它存在很多問題,它只可以監(jiān)聽對象的屬性變化,但是對于數(shù)組的變化時無能為力的。數(shù)組原型中有7個方法可以引起數(shù)組的變化,對于這些方法Vue都需要感知到他們,那怎么實現(xiàn)呢?拿push方法作為例子,需要把原始的push方法覆蓋掉,實現(xiàn)一個新的push,新的push方法要保留原始push方法的功能,還要通知依賴進行更新。
zone.js中的實現(xiàn)和這個思路是一樣的,來看一段簡化的代碼模擬一下setTimeout的補丁過程:
function setTimeoutPatch() { // 存儲原始的setTimeout var originSetTimeout = window['setTimeout']; // 對瀏覽器原生方法的包裹封裝 window.setTimeout = function () { return global['zone']['setTimeout'].apply(global.zone, arguments); }; // 創(chuàng)建包裹方法,提供給上面重寫后的setTimeout使用 Zone.prototype['setTimeout'] = function (fn, delay) { // 先調(diào)用原始方法 originSetTimeout.apply(window, arguments); // 執(zhí)行完原始方法后就可以做其他攔截后需要進行的操作了 ... }; }
是不是對zone.js的基本原理有了了解了呢。