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

資訊專欄INFORMATION COLUMN

Vue.js 源碼學(xué)習(xí)筆記

darkbaby123 / 3284人閱讀

摘要:實(shí)際上,我在看代碼的過(guò)程中順手提交了這個(gè),作者眼明手快,當(dāng)天就進(jìn)行了修復(fù),現(xiàn)在最新的代碼里已經(jīng)不是這個(gè)樣子了而且狀態(tài)機(jī)標(biāo)識(shí)由字符串換成了數(shù)字常量,解析更準(zhǔn)確的同時(shí)執(zhí)行效率也會(huì)更高。

最近饒有興致的又把最新版?Vue.js?的源碼學(xué)習(xí)了一下,覺(jué)得真心不錯(cuò),個(gè)人覺(jué)得 Vue.js 的代碼非常之優(yōu)雅而且精辟,作者本身可能無(wú) (bu) 意 (xie) 提及這些。那么,就讓我來(lái)吧:)

程序結(jié)構(gòu)梳理

Vue.js 是一個(gè)非常典型的 MVVM 的程序結(jié)構(gòu),整個(gè)程序從最上層大概分為

全局設(shè)計(jì):包括全局接口、默認(rèn)選項(xiàng)等

vm 實(shí)例設(shè)計(jì):包括接口設(shè)計(jì) (vm 原型)、實(shí)例初始化過(guò)程設(shè)計(jì) (vm 構(gòu)造函數(shù))

這里面大部分內(nèi)容可以直接跟 Vue.js 的官方 API 參考文檔對(duì)應(yīng)起來(lái),但文檔里面沒(méi)有且值得一提的是構(gòu)造函數(shù)的設(shè)計(jì),下面是我摘出的構(gòu)造函數(shù)最核心的工作內(nèi)容。

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

通過(guò) observer 對(duì) data 進(jìn)行了監(jiān)聽(tīng),并且提供訂閱某個(gè)數(shù)據(jù)項(xiàng)的變化的能力

把 template 解析成一段 document fragment,然后解析其中的 directive,得到每一個(gè) directive 所依賴的數(shù)據(jù)項(xiàng)及其更新方法。比如?v-text="message"?被解析之后 (這里僅作示意,實(shí)際程序邏輯會(huì)更嚴(yán)謹(jǐn)而復(fù)雜):

所依賴的數(shù)據(jù)項(xiàng)?this.$data.message,以及

相應(yīng)的視圖更新方法?node.textContent = this.$data.message

通過(guò) watcher 把上述兩部分結(jié)合起來(lái),即把 directive 中的數(shù)據(jù)依賴訂閱在對(duì)應(yīng)數(shù)據(jù)的 observer 上,這樣當(dāng)數(shù)據(jù)變化的時(shí)候,就會(huì)觸發(fā) observer,進(jìn)而觸發(fā)相關(guān)依賴對(duì)應(yīng)的視圖更新方法,最后達(dá)到模板原本的關(guān)聯(lián)效果。

所以整個(gè) vm 的核心,就是如何實(shí)現(xiàn) observer, directive (parser), watcher 這三樣?xùn)|西

文件結(jié)構(gòu)梳理

Vue.js 源代碼都存放在項(xiàng)目的?src?目錄中,我們主要關(guān)注一下這個(gè)目錄 (事實(shí)上?test/unit/specs?目錄也值得一看,它是對(duì)應(yīng)著每個(gè)源文件的測(cè)試用例)。

src?目錄下有多個(gè)并列的文件夾,每個(gè)文件夾都是一部分獨(dú)立而完整的程序設(shè)計(jì)。不過(guò)在我看來(lái),這些目錄之前也是有更立體的關(guān)系的:

首先是?api/*?目錄,這幾乎是最“上層”的接口封裝,實(shí)際的實(shí)現(xiàn)都埋在了其它文件夾里

然后是?instance/init.js,如果大家希望自頂向下了解所有 Vue.js 的工作原理的話,建議從這個(gè)文件開(kāi)始看起

instance/scope.js:數(shù)據(jù)初始化,相關(guān)的子程序 (目錄) 有?observer/*watcher.jsbatcher.js,而?observer/dep.js?又是數(shù)據(jù)觀察和視圖依賴相關(guān)聯(lián)的關(guān)鍵

instance/compile.js:視圖初始化,相關(guān)的子程序 (目錄) 有?compiler/*directive.jsparsers/*

其它核心要素:directives/*element-directives/*filters/*transition/*

當(dāng)然還有?util/*?目錄,工具方法集合,其實(shí)還有一個(gè)類似的?cache.js

最后是?config.js?默認(rèn)配置項(xiàng)

篇幅有限,如果大家有意“通讀” Vue.js 的話,個(gè)人建議順著上面的整體介紹來(lái)閱讀賞析。

接下來(lái)是一些自己覺(jué)得值得一提的代碼細(xì)節(jié)

一些不容錯(cuò)過(guò)的代碼/程序細(xì)節(jié) this._eventsCount?是什么?

一開(kāi)始看?instance/init.js?的時(shí)候,我立刻注意到一個(gè)細(xì)節(jié),就是?this._eventsCount = {}?這句,后面還有注釋

for $broadcast optimization

非常好奇,然后帶著疑問(wèn)繼續(xù)看了下去,直到看到?api/events.js?中?$broadcast?方法的實(shí)現(xiàn),才知道這是為了避免不必要的深度遍歷:在有廣播事件到來(lái)時(shí),如果當(dāng)前 vm 的?_eventsCount?為?0,則不必向其子 vm 繼續(xù)傳播該事件。而且這個(gè)文件稍后也有?_eventsCount?計(jì)數(shù)的實(shí)現(xiàn)方式。

這是一種很巧妙同時(shí)也可以在很多地方運(yùn)用的性能優(yōu)化方法。

數(shù)據(jù)更新的 diff 機(jī)制

前陣子有很多關(guān)于視圖更新效率的討論,我猜主要是因?yàn)?virtual dom 這個(gè)概念的提出而導(dǎo)致的吧。這次我詳細(xì)看了一下 Vue.js 的相關(guān)實(shí)現(xiàn)原理。

實(shí)際上,視圖更新效率的焦點(diǎn)問(wèn)題主要在于大列表的更新和深層數(shù)據(jù)更新這兩方面,而被熱烈討論的主要是前者 (后者是因?yàn)樾枨笮∵€是沒(méi)爭(zhēng)議我就不得而知了)。所以這里著重介紹一下?directives/repeat.js?里對(duì)于列表更新的相關(guān)代碼。

首先?diff(data, oldVms)?這個(gè)函數(shù)的注釋對(duì)整個(gè)比對(duì)更新機(jī)制做了個(gè)簡(jiǎn)要的闡述,大概意思是先比較新舊兩個(gè)列表的 vm 的數(shù)據(jù)的狀態(tài),然后差量更新 DOM。

第一步:遍歷新列表里的每一項(xiàng),如果該項(xiàng)的 vm 之前就存在,則打一個(gè)?_reused?的標(biāo) (這個(gè)字段我一開(kāi)始看?init.js?的時(shí)候也是困惑的…… 看到這里才明白意思),如果不存在對(duì)應(yīng)的 vm,則創(chuàng)建一個(gè)新的。

第二步:遍歷舊列表里的每一項(xiàng),如果?_reused?的標(biāo)沒(méi)有被打上,則說(shuō)明新列表里已經(jīng)沒(méi)有它了,就地銷毀該 vm。

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

順帶提一句 Vue.js 的元素過(guò)渡動(dòng)畫(huà)處理 (v-transition) 也設(shè)計(jì)得非常巧妙,感興趣的自己看吧,就不展開(kāi)介紹了

組件的?[keep-alive]?特性

Vue.js 為其組件設(shè)計(jì)了一個(gè)?[keep-alive]?的特性,如果這個(gè)特性存在,那么在組件被重復(fù)創(chuàng)建的時(shí)候,會(huì)通過(guò)緩存機(jī)制快速創(chuàng)建組件,以提升視圖更新的性能。代碼在?directives/component.js

數(shù)據(jù)監(jiān)聽(tīng)機(jī)制

如何監(jiān)聽(tīng)某一個(gè)對(duì)象屬性的變化呢?我們很容易想到?Object.defineProperty?這個(gè) API,為此屬性設(shè)計(jì)一個(gè)特殊的 getter/setter,然后在 setter 里觸發(fā)一個(gè)函數(shù),就可以達(dá)到監(jiān)聽(tīng)的效果。

不過(guò)數(shù)組可能會(huì)有點(diǎn)麻煩,Vue.js 采取的是對(duì)幾乎每一個(gè)可能改變數(shù)據(jù)的方法進(jìn)行 prototype 更改:

但這個(gè)策略主要面臨兩個(gè)問(wèn)題:

無(wú)法監(jiān)聽(tīng)數(shù)據(jù)的?length,導(dǎo)致?arr.length?這樣的數(shù)據(jù)改變無(wú)法被監(jiān)聽(tīng)

通過(guò)角標(biāo)更改數(shù)據(jù),即類似?arr[2] = 1?這樣的賦值操作,也無(wú)法被監(jiān)聽(tīng)

為此 Vue.js 在文檔中明確提示不建議直接角標(biāo)修改數(shù)據(jù)

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

path 解析器的狀態(tài)機(jī)設(shè)計(jì)

首先要說(shuō)?parsers?文件夾里有各種“財(cái)寶”等著大家挖掘!認(rèn)真看一看一定不會(huì)后悔的

parsers/path.js?主要的職責(zé)是可以把一個(gè) JSON 數(shù)據(jù)里的某一個(gè)“路徑”下的數(shù)據(jù)取出來(lái),比如:

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

所以對(duì)?path?字符串的解析成為了它的關(guān)鍵。Vue.js 是通過(guò)狀態(tài)機(jī)管理來(lái)實(shí)現(xiàn)對(duì)路徑的解析的:

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

也許看得更清楚一點(diǎn)了,當(dāng)然也能發(fā)現(xiàn)其中有一點(diǎn)小問(wèn)題,就是源代碼中?inIdent?這個(gè)狀態(tài)是具有二義性的,它對(duì)應(yīng)到了圖中的三個(gè)地方,即?in ident?和兩個(gè)?in (quoted) ident

實(shí)際上,我在看代碼的過(guò)程中順手提交了這個(gè) bug,作者眼明手快,當(dāng)天就進(jìn)行了修復(fù),現(xiàn)在最新的代碼里已經(jīng)不是這個(gè)樣子了:

而且狀態(tài)機(jī)標(biāo)識(shí)由字符串換成了數(shù)字常量,解析更準(zhǔn)確的同時(shí)執(zhí)行效率也會(huì)更高。

一點(diǎn)自己的思考

首先是視圖的解析過(guò)程,Vue.js 的策略是把 element 或 template string 先統(tǒng)一轉(zhuǎn)換成 document fragment,然后再分解和解析其中的子組件和 directives。我覺(jué)得這里有一定的性能優(yōu)化空間,畢竟 DOM 操作相比之余純 JavaScript 運(yùn)算還是會(huì)慢一些。

然后是基于移動(dòng)端的思考,Vue.js 雖確實(shí)已經(jīng)非常非常小巧了 (min+gzip 之后約 22 kb),但它是否可以更小,繼續(xù)抽象出常用的核心功能,同時(shí)更快速,也是個(gè)值得思考的問(wèn)題。

第三我非常喜歡通過(guò) Vue.js 進(jìn)行模塊化開(kāi)發(fā)的模式,Vue 是否也可以借助類似 web components + virtual dom 的形態(tài)把這樣的開(kāi)發(fā)模式帶到更多的領(lǐng)域,也是件很有意義的事情。

總結(jié)

Vue.js 里的代碼細(xì)節(jié)還不僅于此,比如:

cache.js?里的緩存機(jī)制設(shè)計(jì)和場(chǎng)景運(yùn)用 (如在?parsers/path.js?中)

parsers/template.js?里的?cloneNode?方法重寫(xiě)和對(duì) HTML 自動(dòng)補(bǔ)全機(jī)制的兼容

在開(kāi)發(fā)和生產(chǎn)環(huán)境分別用注釋結(jié)點(diǎn)和不可見(jiàn)文本結(jié)點(diǎn)作為視圖的“占位符”等等

自己也在閱讀代碼,了解 Vue.js 的同時(shí)學(xué)到了很多東西,同時(shí)我覺(jué)得代碼實(shí)現(xiàn)只是 Vue.js 優(yōu)秀的要素之一,整體的程序設(shè)計(jì)、API 設(shè)計(jì)、細(xì)節(jié)的取舍、項(xiàng)目的工程考量都非常棒!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/99471.html

相關(guān)文章

  • 前端學(xué)習(xí)資源匯總

    摘要:建立該倉(cāng)庫(kù)的目的主要是整理收集學(xué)習(xí)資源,統(tǒng)一管理,方便隨時(shí)查找。目前整合的學(xué)習(xí)資源只是前端方向的,可能會(huì)存在漏缺比較好的資源,需要慢慢的完善它,歡迎在該上補(bǔ)充資源或者提供寶貴的建議。 說(shuō)明 平時(shí)的學(xué)習(xí)資源都比較的凌亂,看到好的資源都是直接收藏在瀏覽器的收藏夾中,這樣其實(shí)并不方便,整理在云筆記上,也不方便查看修改記錄,索性就整理在 github 上并開(kāi)源出來(lái),希望幫助大家能夠更快的找到需...

    SnaiLiu 評(píng)論0 收藏0
  • Vue.js 源碼學(xué)習(xí)筆記

    摘要:實(shí)際上,我在看代碼的過(guò)程中順手提交了這個(gè),作者眼明手快,當(dāng)天就進(jìn)行了修復(fù),現(xiàn)在最新的代碼里已經(jīng)不是這個(gè)樣子了而且狀態(tài)機(jī)標(biāo)識(shí)由字符串換成了數(shù)字常量,解析更準(zhǔn)確的同時(shí)執(zhí)行效率也會(huì)更高。 最近饒有興致的又把最新版?Vue.js?的源碼學(xué)習(xí)了一下,覺(jué)得真心不錯(cuò),個(gè)人覺(jué)得 Vue.js 的代碼非常之優(yōu)雅而且精辟,作者本身可能無(wú) (bu) 意 (xie) 提及這些。那么,就讓我來(lái)吧:) 程序結(jié)構(gòu)梳...

    jsdt 評(píng)論0 收藏0
  • Vue.js學(xué)習(xí)系列二 —— vuex學(xué)習(xí)實(shí)踐筆記(附DEMO)

    摘要:有興趣的同學(xué)可以查看之前發(fā)布的文章學(xué)習(xí)系列一學(xué)習(xí)實(shí)踐筆記附學(xué)習(xí)系列二學(xué)習(xí)實(shí)踐筆記附學(xué)習(xí)系列三和網(wǎng)絡(luò)傳輸相關(guān)知識(shí)的學(xué)習(xí)實(shí)踐學(xué)習(xí)系列四打包工具的使用學(xué)習(xí)系列五從來(lái)聊聊學(xué)習(xí)系列項(xiàng)目地址項(xiàng)目暫時(shí)有點(diǎn)亂,之后會(huì)進(jìn)行整理優(yōu)化。 上次學(xué)習(xí)了vue-router的使用,讓我能夠在各個(gè)頁(yè)面間切換,將頁(yè)面搭建了起來(lái)。這次則要學(xué)習(xí)vue的狀態(tài)管理模式——vuex。它類似于redux來(lái)應(yīng)用的全局狀態(tài)。 注:本...

    DobbyKim 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<