国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

【干貨】vue源代碼簡單解析

ccj659 / 2526人閱讀

摘要:解析器的狀態機設計首先要說文件夾里有各種財寶等著大家挖掘認真看一看一定不會后悔的主要的職責是可以把一個數據里的某一個路徑下的數據取出來,比如所以對字符串的解析成為了它的關鍵。

最近饒有興致的又把最新版 Vue.js 的源碼學習了一下,覺得真心不錯,個人覺得 Vue.js 的代碼非常之優雅而且精辟,作者本身可能無 (bu) 意 (xie) 提及這些。那么,就讓我來吧:)

程序結構梳理

Vue 程序結構

Vue.js 是一個非常典型的 MVVM 的程序結構,整個程序從最上層大概分為

全局設計:包括全局接口、默認選項等
vm 實例設計:包括接口設計 (vm 原型)、實例初始化過程設計 (vm 構造函數)
這里面大部分內容可以直接跟 Vue.js 的官方 API 參考文檔對應起來,但文檔里面沒有且值得一提的是構造函數的設計,下面是我摘出的構造函數最核心的工作內容。

Vue 實例初始化

整個實例初始化的過程中,重中之重就是把數據 (Model) 和視圖 (View) 建立起關聯關系。Vue.js 和諸多 MVVM 的思路是類似的,主要做了三件事:

通過 observer 對 data 進行了監聽,并且提供訂閱某個數據項的變化的能力
把 template 解析成一段 document fragment,然后解析其中的 directive,得到每一個 directive 所依賴的數據項及其更新方法。比如 v-text="message" 被解析之后 (這里僅作示意,實際程序邏輯會更嚴謹而復雜):
所依賴的數據項 this.$data.message,以及
相應的視圖更新方法 node.textContent = this.$data.message
通過 watcher 把上述兩部分結合起來,即把 directive 中的數據依賴訂閱在對應數據的 observer 上,這樣當數據變化的時候,就會觸發 observer,進而觸發相關依賴對應的視圖更新方法,最后達到模板原本的關聯效果。
所以整個 vm 的核心,就是如何實現 observer, directive (parser), watcher 這三樣東西

文件結構梳理

Vue.js 源代碼都存放在項目的 src 目錄中,我們主要關注一下這個目錄 (事實上 test/unit/specs 目錄也值得一看,它是對應著每個源文件的測試用例)。

src 目錄下有多個并列的文件夾,每個文件夾都是一部分獨立而完整的程序設計。不過在我看來,這些目錄之前也是有更立體的關系的:

Vue 文件結構

首先是 api/* 目錄,這幾乎是最“上層”的接口封裝,實際的實現都埋在了其它文件夾里
然后是 instance/init.js,如果大家希望自頂向下了解所有 Vue.js 的工作原理的話,建議從這個文件開始看起
instance/scope.js:數據初始化,相關的子程序 (目錄) 有 observer/*、watcher.js、batcher.js,而 observer/dep.js 又是數據觀察和視圖依賴相關聯的關鍵
instance/compile.js:視圖初始化,相關的子程序 (目錄) 有 compiler/、directive.js、parsers/
其它核心要素:directives/、element-directives/、filters/、transition/
當然還有 util/* 目錄,工具方法集合,其實還有一個類似的 cache.js
最后是 config.js 默認配置項
篇幅有限,如果大家有意“通讀” Vue.js 的話,個人建議順著上面的整體介紹來閱讀賞析。

接下來是一些自己覺得值得一提的代碼細節

一些不容錯過的代碼/程序細節

this._eventsCount 是什么?

一開始看 instance/init.js 的時候,我立刻注意到一個細節,就是 this._eventsCount = {} 這句,后面還有注釋

eventsCount1

for $broadcast optimization

非常好奇,然后帶著疑問繼續看了下去,直到看到 api/events.js 中 $broadcast 方法的實現,才知道這是為了避免不必要的深度遍歷:在有廣播事件到來時,如果當前 vm 的 _eventsCount 為 0,則不必向其子 vm 繼續傳播該事件。而且這個文件稍后也有 _eventsCount 計數的實現方式。

eventsCount2

eventsCount3

這是一種很巧妙同時也可以在很多地方運用的性能優化方法。

數據更新的 diff 機制

前陣子有很多關于視圖更新效率的討論,我猜主要是因為 virtual dom 這個概念的提出而導致的吧。這次我詳細看了一下 Vue.js 的相關實現原理。

實際上,視圖更新效率的焦點問題主要在于大列表的更新和深層數據更新這兩方面,而被熱烈討論的主要是前者 (后者是因為需求小還是沒爭議我就不得而知了)。所以這里著重介紹一下 directives/repeat.js 里對于列表更新的相關代碼。

diff1

首先 diff(data, oldVms) 這個函數的注釋對整個比對更新機制做了個簡要的闡述,大概意思是先比較新舊兩個列表的 vm 的數據的狀態,然后差量更新 DOM。

diff2

第一步:便利新列表里的每一項,如果該項的 vm 之前就存在,則打一個 _reused 的標 (這個字段我一開始看 init.js 的時候也是困惑的…… 看到這里才明白意思),如果不存在對應的 vm,則創建一個新的。

diff3

第二步:便利舊列表里的每一項,如果 _reused 的標沒有被打上,則說明新列表里已經沒有它了,就地銷毀該 vm。

diff4

第三步:整理新的 vm 在視圖里的順序,同時還原之前打上的 _reused 標。就此列表更新完成。

順帶提一句 Vue.js 的元素過渡動畫處理 (v-transition) 也設計得非常巧妙,感興趣的自己看吧,就不展開介紹了

組件的 [keep-alive] 特性

keepAlive1

keepAlive2

Vue.js 為其組件設計了一個 [keep-alive] 的特性,如果這個特性存在,那么在組件被重復創建的時候,會通過緩存機制快速創建組件,以提升視圖更新的性能。代碼在 directives/component.js。

數據監聽機制

如何監聽某一個對象屬性的變化呢?我們很容易想到 Object.defineProperty 這個 API,為此屬性設計一個特殊的 getter/setter,然后在 setter 里觸發一個函數,就可以達到監聽的效果。

不過數組可能會有點麻煩,Vue.js 采取的是對幾乎每一個可能改變數據的方法進行 prototype 更改:

ob_array1

但這個策略主要面臨兩個問題:

無法監聽數據的 length,導致 arr.length 這樣的數據改變無法被監聽
通過角標更改數據,即類似 arr[2] = 1 這樣的賦值操作,也無法被監聽
為此 Vue.js 在文檔中明確提示不建議直接角標修改數據

同時 Vue.js 提供了兩個額外的“糖方法” $set 和 $remove 來彌補這方面限制帶來的不便。整體上看這是個取舍有度的設計。我個人之前在設計數據綁定庫的時候也采取了類似的設計 (一個半途而廢的內部項目就不具體獻丑了),所以比較認同也有共鳴。

path 解析器的狀態機設計

首先要說 parsers 文件夾里有各種“財寶”等著大家挖掘!認真看一看一定不會后悔的

parsers/path.js 主要的職責是可以把一個 JSON 數據里的某一個“路徑”下的數據取出來,比如:

var path = "a.b[1].v"
var obj = {
  a: {
    b: [
      {v: 1},
      {v: 2},
      {v: 3}
    ]
  }
}
parse(obj, path) // 2

所以對 path 字符串的解析成為了它的關鍵。Vue.js 是通過狀態機管理來實現對路徑的解析的:

咋一看很頭大,不過如果再稍微梳理一下:

也許看得更清楚一點了,當然也能發現其中有一點小問題,就是源代碼中 inIdent 這個狀態是具有二義性的,它對應到了圖中的三個地方,即 in ident 和兩個 in (quoted) ident。

總結

Vue.js 里的代碼細節還不僅于此,比如:

cache.js 里的緩存機制設計和場景運用 (如在 parsers/path.js 中)
parsers/template.js 里的 cloneNode 方法重寫和對 HTML 自動補全機制的兼容
在開發和生產環境分別用注釋結點和不可見文本結點作為視圖的“占位符”等等
自己也在閱讀代碼,了解 Vue.js 的同時學到了很多東西,同時我覺得代碼實現只是 Vue.js 優秀的要素之一,整體的程序設計、API 設計、細節的取舍、項目的工程考量都非常棒!

總之,分享一些自己的收獲和代碼的細節,希望可以幫助大家開闊思路,提供靈感

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/87291.html

相關文章

  • 干貨--手把手擼vue移動UI框架: 滑動加載

    摘要:前言在我們移動端還有一個很常用的組件,那就是滑動加載更多組件。平常我們看到的很多插件實現相當復雜就覺得這個組件很難,其實不是的這個組件其實可以很簡單的就實現出來,而且體驗也能非常的棒當然我們沒有實現下拉刷新功能下面我們就一起來實現這個組件。 前言 在我們移動端還有一個很常用的組件,那就是滑動加載更多組件。平常我們看到的很多插件實現相當復雜就覺得這個組件很難,其實不是的!!這個組件其實可...

    Harpsichord1207 評論0 收藏0
  • 做IT這幾年,我整理了這些干貨想要送給你!

    摘要:資源獲取方式根據下面的索引,大家可以選擇自己需要的資源,然后在松哥公眾號牧碼小子后臺回復對應的口令,就可以獲取到資源的百度云盤下載地址。公眾號二維碼如下另外本文會定期更新,松哥有新資源的時候會及時分享給大家,歡迎各位小伙伴保持關注。 沒有一條路是容易的,特別是轉行計算機這條路。 松哥接觸過很多轉行做開發的小伙伴,我了解到很多轉行人的不容易,記得松哥大二時剛剛決定轉行計算機,完全不知道這...

    王晗 評論0 收藏0
  • JavaScript精編干貨

    摘要:老姚淺談怎么學鑒于時不時,有同學私信問我老姚,下同怎么學前端的問題。擼碼聽歌,全局控制。 淺析用 js 解析 xml 的方法 由于項目上需要解析 xml,于是各種百度,然后自己總結了下各個主流瀏覽器解析 xml 的方法,只能是很淺顯的知道他的用法,但是還沒有深層次的研究。 裝 X - 建立自己的斗圖網站庫 之前加過一個斗圖群,看到很多經典的表情,然后就收藏到了 QQ, 迫于本屌絲開不起...

    Fourierr 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<