Vue響應式系統(tǒng)的原理詳解
vue響應式系統(tǒng)的基本原理
我們使用vue時,對數(shù)據(jù)進行操作,就能影響對應的視圖。那么這種機制是怎么實現(xiàn)的呢?
思考一下,是不是就好像我們對數(shù)據(jù)的操作 被“某人”監(jiān)視了?一旦我們對數(shù)據(jù)進行了更改,“某人”就能感應到,并幫我們更新視圖
那么這個“某人”到底是誰呢?其實它很普通,就是我們基礎里面有學過的?Object.defineProperty,使用它來對數(shù)據(jù)進行一下加工,就能實現(xiàn)當數(shù)據(jù)被讀時,執(zhí)行“讀”的回調(diào)函數(shù);數(shù)據(jù)被寫時,執(zhí)行“寫”的回調(diào)函數(shù)。
接下來,我們將簡單回顧該方法的使用,再用幾個實戰(zhàn)小例子帶大家徹底弄懂這個原理。
1.回顧一下Object.defineProperty的用法
參數(shù)解釋:
obj: 目標對象 prop: 需要操作的目標對象的屬性名 descriptor: 描述符 return value 傳入對象
descriptor的一些屬性,簡單介紹幾個屬性。
enumerable,屬性是否可枚舉,默認 false。 configurable,屬性是否可以被修改或者刪除,默認 false。 writable,屬性是否可以被修改,默認false get,獲取屬性的方法。 set,設置屬性的方法。
完整用法:
Object.defineProperty(obj, prop, descriptor)
2.實戰(zhàn)1:使用 Object.defineProperty 對 person的age屬性 進行監(jiān)聽
踩坑
看下面代碼,乍一看是不是感覺沒什么不妥?
當有人讀取person的age屬性時,我就把person的age屬性return出去;當有人修改person的age屬性,我就直接修改person.age的值。
但是!同學們,運行了一下,雖然沒報錯,但是編譯器一直瘋狂輸出“@@有人讀取了age屬性”。
這是為啥呢?你想想,你在get函數(shù)里面直接return person.age,這算不算又一次讀取了person的age屬性呢?此時程序又去執(zhí)行age的get函數(shù),反反復復。
打個比方哈,相當于 你想讀取age,于是你告訴編譯器,我要輸出person.age,好的,編譯器去查person.age,發(fā)現(xiàn)它有get函數(shù),于是執(zhí)行get函數(shù),此時你以為你要拿到它的值了,沒想到get函數(shù)里面又告訴編譯器,我要person.age。這樣的話,就形成了死循環(huán)?。?/p>
那要怎么解決呢?我在get里面不能直接返回 person.age,那我要怎么拿到這個屬性的值呢?
答:是不是可以用變量來替代呢?
我把person.age的值放在變量ageNumber中,我要讀的時候,就返回ageNumber的值;要修改的時候,就修改ageNumber的值;
這樣不就避免了在get,set函數(shù)里面直接用person.age來訪問嗎?
正確代碼
這時,效果就完成了,讀取和修改的時候,都能被監(jiān)聽到。
3.數(shù)據(jù)代理
數(shù)據(jù)代理是什么意思呢?
答:簡單解釋一下,就是通過一個對象 代理 對另一個對象中屬性的操作 (讀/寫)
有點抽象對嗎?用下面的小例子來解釋一下吧。
當老師想查看 或者 修改學生的成績時,直接在老師這個對象上操作就行了,不需要直接去操作student對象。
這也就是上面想解釋的,通過 老師對象(teacher) 代理 了學生對象(student)中的成績屬性(score)的操作 (讀/寫)
4.vue中實現(xiàn)響應式思路
有一點vue2基礎的同學們應該知道,我們在vue中data() {} 中定義的數(shù)據(jù),是不是都會被掛載到vm對象上去?然后我們是通過 this.數(shù)據(jù)名 來對數(shù)據(jù)進行操作的,對嗎?
那這個是不是就相當于上面的小例子中的情景呢,這里是vm對象 代理 你定義的data對象中的屬性的操作(讀/寫)
再用個例子完整實現(xiàn)一下vue的響應式原理
把data對象中的所有屬性 交給 vm對象進行代理(讓vm 掌控data對象中的屬性的 (讀/寫) 操作 )當數(shù)據(jù)變化時,能更新對應視圖
總結
1.Vue中的數(shù)據(jù)代理:
通過vm對象來代理data對象中屬性的操作(讀/寫)
2.Vue中數(shù)據(jù)代理的好處:
更加方便的操作data中的數(shù)據(jù)
3.基本原理:
通過Object.defineProperty()
把data對象中所有屬性添加到vm上。
為每一個添加到vm上的屬性,都指定一個getter/setter。
在getter/setter
內(nèi)部去操作(讀/寫)data中對應的屬性。
4.vue中實現(xiàn)響應式思路
不使用數(shù)據(jù)代理,直接把數(shù)據(jù) 賦值 掛載到vm上。
1.下圖的方法是對 數(shù)據(jù)對象設置get,set的通用方法
2.在new一個Vue時,就會直接把用戶傳入的data對象,掛載到Vue實例身上
再對Vue實例上面的data對象進行監(jiān)視(響應式處理)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內(nèi)容!
相關文章
微信小程序?qū)崙?zhàn)基于vue2實現(xiàn)瀑布流的代碼實例
瀑布流,又稱瀑布流式布局,是比較流行的一種網(wǎng)站頁面布局,視覺表現(xiàn)為參差不齊的多欄布局,隨著頁面滾動條向下滾動,這種布局還會不斷加載數(shù)據(jù)塊并附加至當前尾部,這篇文章主要介紹了微信小程序?qū)崙?zhàn),基于vue2實現(xiàn)瀑布流,需要的朋友可以參考下2022-12-12關于Elementui中toggleRowSelection()方法實現(xiàn)分頁切換時記錄之前選中的狀態(tài)
這篇文章主要介紹了關于Elementui中toggleRowSelection()方法實現(xiàn)分頁切換時記錄之前選中的狀態(tài),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03web面試MVC與MVVM區(qū)別及Vue為什么不完全遵守MVVM解答
這篇文章主要介紹了web面試中常問問題,MVC與MVVM區(qū)別以及Vue為什么不完全遵守MVVM的難點解答,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-09-09