eltree ref什么时候有_Vue3响应式系统源码解析-Ref篇
文章轉載自:https://zhuanlan.zhihu.com/p/85978064
我們閱讀源碼的原因是什么?無非是1:學習;2:更好的使用這個庫。如果只是想大致的了解下原理,倒不必花時間閱讀源碼,幾句話,幾張圖就能搞清楚,網上搜搜應該就有很多。因此,閱讀源碼的過程一定是要對不明白的地方深入了解,肯定是很費時間的。
在這過程中,有些知識點,跟庫本身可能沒什么關系,但如果不懂,又難繼續理解。對于這些知識點,我會盡量少的解釋,但會貼上盡量完善的文檔,方便不了解的同學先閱讀學習。
前言
在上篇文章中說道,ref是最影響源碼閱讀的文件。但如果不先搞明白它,看其他的只會更暈。我先幫大家理清ref的邏輯跟概念。
由于現在(2019/10/9)vue@3還未正式發版,大家還不熟悉其相關的用法。上篇文章雖然介紹了不少,但其實還是有不少疑問。在閱讀本篇文章之前,如果有時間,建議先閱讀Vue官方對Composition API的介紹: 1. Vue Composition API 2. Ref Vs Reactive
讀完關于Composition API的介紹,會對了解本庫有更多認識,便于更好的理解源碼。
ref跟reactive是整個源碼中的核心,通過這兩個方法創建了響應式數據。要想完全吃透reactivity,必須先吃透這兩個。
Ref
ref最重要的作用,其實是提供了一套Ref類型,我們先來看,它到底是個怎么樣的數據類型。(為了更好的做解釋,我會調整源碼中的接口、類型、函數等聲明順序,并會增加一些注釋方便閱讀)
要想了解UnwrapNestedRefs與UnwrapRef,必須先要了解ts中的infer。如果之前不了解,請先閱讀相關文檔。看完文檔,再建議去google一些案例看看加深下印象。
現在我們假設你了解了infer概念,也了解了它的日常用法。再來看源碼:
如果還是懵,建議后續再去看看infer的相關介紹。在這我們直接拋結果:
Ref是這樣的一種數據結構:它有個key為Symbol的屬性做類型標識,有個屬性value用來存儲數據。這個數據可以是任意的類型,唯獨不能是被嵌套了Ref類型的類型。 具體來說就是不能是這樣 Array 或者這樣 { [key]: Ref }。但很奇怪的是,這樣Ref 又是可以的。具體為什么也不知道,所以我勇敢地提了個PR...
(果然Ref 是不夠完美的,2019.10.10晚,我這PR被合并了。大家遇到疑問時,也可以勇敢的提PR,說不定就被合了....)
另外,Map、Set、WeakMap、WeakSet也是不支持解套的。說明Ref數據的value也有可能是Map這樣的數據類型。
說回Ref,從上篇文章中,我們已經了解到,Ref類型的數據,是一種響應式的數據。然后我們看其具體實現:
其實最難理解的就在于這個ref函數。我們看到,這里也定義了get/set,卻沒有任何Proxy相關的操作。在之前的信息中我們知道reactive能構建出響應式數據,但要求傳參必須是對象。但ref的入參是對象時,同樣也需要reactive做轉化。那ref這個函數的目的到底是什么呢?為什么需要有它?
在文章開頭,我貼了這份官方介紹Ref vs Reactive,這其中其實已經說的很明白。
However, the problem with going reactive-only is that the consumer of a composition function must keep the reference to the returned object at all times in order to retain reactivity. The object cannot be destructured or spread:
對于基本數據類型,函數傳遞或者對象解構時,會丟失原始數據的引用,換言之,我們沒法讓基本數據類型,或者解構后的變量(如果它的值也是基本數據類型的話),成為響應式的數據。
// 我們是永遠沒辦法讓`a`或`x`這樣的基本數據成為響應式的數據的,Proxy也無法劫持基本數據。const a = 1;const { x: 1 } = { x: 1 }但是有時候,我們確實就是想一個數字、一個字符串是響應式的,或者就是想利用解構的寫法。那怎么辦呢?只能通過創建一個對象,也即是源碼中的Ref數據,然后將原始數據保存在Ref的屬性value當中,再將它的引用返回給使用者。既然是我們自己創造出來的對象,也就沒必要使用Proxy再做代理了,直接劫持這個value的get/set即可,這就是ref函數與Ref類型的由來。
不過單靠ref還沒法解決對象解構的問題,它只是將基本數據保持在一個對象的value中,以實現數據響應式。對于對象的解構還需要另外一個函數:toRefs。
通過遍歷對象,將每個屬性值都轉成Ref數據,這樣解構出來的還是Ref數據,自然就保持了響應式數據的引用。但是源碼中有一點要注意,toRefs函數中引用的是toProxyRef而不是ref,它并不會在get/set中注入track跟trigger,也就是說,向toRefs傳入一個正常的對象,是不會返回一個響應式的數據的。必須要傳遞一個已經被reactive執行返回的對象才能有響應式的效果。感覺這點可以優化,暫時也不知道小右這樣做的原因是什么。由于這里會牽扯到track跟trigger,而這兩個在我寫本文時還沒研究,就沒膽子提PR了。
到這,我們就把ref的源碼給看完了。
總結
以上是生活随笔為你收集整理的eltree ref什么时候有_Vue3响应式系统源码解析-Ref篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 测试眉形的有哪个软件_这五款自动化软件测
- 下一篇: 两对光纤收发器用网线连接_为什么现在的人