摘要:在讀取訪問器屬性時,就會調用函數,該函數負責返回有效的值在寫入訪問器屬性時,會調用函數并傳入新值,該函數負責決定如何處理數據,但是這兩個函數不一定非要同時存在。
前言
Vue最明顯的特性之一便是它的響應式系統,其數據模型即是普通的 JavaScript 對象。而當你讀取或寫入它們時,視圖便會進行響應操作。文章簡要闡述下其實現原理,如有錯誤,還請不吝指正。個人博客鏈接:hiybm.cn
響應式data
{{ message }}const vm = new Vue({ el: "#exp", data: { message: "This is A" } }) vm.message = "This is B" // 響應式 vm._message = "This is C" // 非響應式
上述代碼中,data是Vue實例的數據對象,當實例初始化時,Vue 會遍歷 data 中的所有屬性,并且使用 Object.definePropery 把這些屬性全都轉為 getter/setter ,從而讓 data 的屬性能夠響應數據變化。另外,Object.defineProperty 是 ES5 中一個無法 shim(墊片) 的特性,這也就是為什么 Vue 不支持 IE8 以及更低版本瀏覽器的原因。對象必須是純粹的對象 (含有零個或多個的 key/value 鍵值對):瀏覽器 API 創建的原生對象。所以,在data中聲明過的message是響應式數據,而由于_message是在data外使用 Vue 實例增加的數據,所以亦不屬于響應式。
關于Object.definePropery
Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性,并返回這個對象。這個API是實現響應式數據的關鍵所在。
Syntax: Object.defineProperty(obj, prop, descriptor)
obj: 要定義屬性的對象
prop: 要定義或修改的屬性的名稱
descriptor: 將被定義或修改的屬性描述符。
Tips: 要知道ECMAScript中有兩種屬性:數據屬性和訪問器屬性。這里的descriptor可取值有數據屬性和訪問器屬性。
數據屬性: 包含一個數據值的位置,在此位置可以進行讀寫操作,有以下特性:
[[Configurable]]:對屬性的操作可配置性開關,如刪除,修改。默認值為true。
[[Enumberble]]:是否可枚舉(通過for-in)。默認值為true。
[[Writable]]:能否修改屬性的值。默認值為true。
[[value]]:包含這個屬性的數據值,讀取時從該位置讀,寫入時把新值存到該位置。默認值為undefined。
訪問器屬性: 不包含數據值,包含一個函數對(getter/setter)。特性如下:
[[Configurable]]:對屬性的操作可配置性開關,如刪除,修改。默認值為true。
[[Enumberble]]:是否可枚舉(通過for-in)。默認值為true。
[[Get]]:讀取屬性時調用的函數。默認值為undefined。
[[Set]]:寫入屬性時調用的函數。默認值為undefined。
Tips: 在讀取訪問器屬性時,就會調用getter函數,該函數負責返回有效的值;在寫入訪問器屬性時,會調用setter函數并傳入新值,該函數負責決定如何處理數據,但是這兩個函數不一定非要同時存在。Vue便是利用getter/setter這一特性來實現的響應系統。
示例代碼:
// 定義一個book對象,_year和edition都屬于數據屬性。 var book = { _year : 2004, edition : 1 }; // 對book對象創建 year 訪問器屬性。 Object.defineProperty(book, "year",{ // 讀取 year 訪問器屬性時,get() 方法返回 _year 的值。 get : function () { console.info(this._year, "get"); // 2004 return this._year; }, // 寫入 year 訪問器屬性時,set() 方法對新值進行操作。 set : function (newValue) { if (newValue > 2004) { this._year = newValue; console.info(this._year, "set") // 2005 this.edition += newValue - 2004; } } }); // 讀取 year 訪問器屬性時會返回_year的值。 book.year; // 寫入 year 訪問器屬性時會調用set() 函數,進行操作。 book.year = 2005; console.info(book.edition) // 2 console.info(book) // 此處藏有彩蛋。
watcher
官方表述:每個組件實例都有相應的 watcher 實例對象,它會在組件渲染的過程中把屬性記錄為依賴,之后當依賴項的 setter 被調用時,會通知 watcher 重新計算,從而致使它關聯的組件得以更新。
如下圖所示:
Tips:模板中每個指令/數據綁定都有一個對應的 watcher 對象。其中 watcher扮演的角色相當于是一個紐帶,這個紐帶的作用就是依賴收集。
END
文中還有部分深層細節沒有講述到,后續我也會接著更新系列文章來進一步深深深究vue底層的響應式原理,SYNT。BTW,如果有同學發現彩蛋了,歡迎在評論區交流。?
參考鏈接
Object.defineproperty
深入響應式原理
深入淺出之vue響應式原理
Javascript高級程序設計(第3版)6.1章節
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90258.html
摘要:問題為什么修改即可觸發更新和的關聯關系官方介紹的官網文檔,對響應式屬性的原理有一個介紹。因此本文在源碼層面,對響應式原理進行梳理,對關鍵步驟進行解析。 描述 ?我們通過一個簡單的 Vue應用 來演示 Vue的響應式屬性: html: {{message}} js: let vm = new Vue({ el: #ap...
摘要:所以我今后打算把每一個內容分成白話版和源碼版。有什么錯誤的地方,感謝大家能夠指出響應式系統我們都知道,只要在實例中聲明過的數據,那么這個數據就是響應式的。什么是響應式,也即是說,數據發生改變的時候,視圖會重新渲染,匹配更新為最新的值。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于 V...
寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關注公眾號也可以吧 【Vue原理】Props - 源碼版 今天記錄 Props 源碼流程,哎,這東西,就算是研究過了,也真是會隨著時間慢慢忘記的。 幸好我做...
摘要:原型方法通過原型方法方法來掛載實例。當響應式屬性發生變化時,會通知依賴列表中的對象進行更新。此時,對象執行方法,重新渲染節點。在執行過程中,如果需要讀取響應式屬性,則會觸發響應式屬性的。總結響應式屬性的原理 vue實例 初始化 完成以后,接下來就要進行 掛載。 vue實例掛載,即為將vue實例對應的 template模板,渲染成 Dom節點。 原型方法 - $mount ? 通過原...
摘要:對象用戶看到的對象用戶看到的是這個對象即是實際使用的對象實際使用的對象復制更新相應的代碼實現對象代理響應式原理前提官網說過,限于現代瀏覽器限制,無法監測通過這種方式添加的屬性,所以,他的響應式是建立在實例化對象的時候,預定義屬性的基礎上的。 1. Vue 對象 1.1 用戶看到的對象 var app = new Vue({ el: #app , /* * 用...
閱讀 3035·2023-04-25 20:09
閱讀 3318·2021-11-23 09:51
閱讀 1971·2021-11-22 15:25
閱讀 3348·2021-11-18 10:02
閱讀 2747·2021-09-27 13:56
閱讀 1304·2019-08-30 15:44
閱讀 1149·2019-08-30 13:21
閱讀 3322·2019-08-30 11:05