這是一個由 simviso 團隊對 JSConf.Asia 中關於 前端框架設計取捨 相關話題進行翻譯的文檔,內容並不是直譯,其中有一些是筆者自身的思考。而分享者正是 Vue.js 的做者 @尤雨溪,Vue 倉庫地址:github.com/vuejs/vue前端
讓咱們一塊兒來了解下在當前框架三足鼎立的局勢下,如何直接透過框架自己瞭解到更多有關框架設計中的的權衡,以及 Vue 是如何進行取捨的。vue
視頻地址:node
視頻翻譯版權歸 simviso 全部react
前端公衆號git
你們好,很高興來到這裏。你今天過得怎麼樣? OKgithub
我很確定你已經看過不少講座了,也知道今天此次課程,但願此次不會太無聊,可是仍是要給那些不認識個人人簡單地介紹一下我本身。算法
個人名字叫 Evan You,個人推特帳號是 Youyuxi,個人中文名字就是 Youyuxi。從2016年開始我就是一個獨立的開源開發者。vuex
也就是說我如今已經獨立開源三年了,主要從事 Vue.js。npm
大家中有多少人在真正的使用它?數組
很好
它從 2013 年開始做爲個人一個業餘項目 ,我從 2016 年開始全職維護它。在多年的框架設計工做中,我學到了不少東西,這也給了我不少關於內部設計的觀點。人們在構建正確的框架時作出的一些權衡決策。
大家中有多少人還記得 2013年 的那段時間,那時可能天天都會有一個新的 JavaScript 框架出現,NBC 有一個相似 40,50個框架的列表,這些框架都在構建相同的東西,Vue 差很少是從它們的時代開始的,當時我只是在研究一些現有的解決方案,並試圖找出若是我構建這樣的東西,我會怎麼作。
但很明顯,我對應該作什麼的想法隨着時間的推移而發生了很大變化。
但今天我將討論其中的一些發現,特別是前端框架設計。
我敢打賭,不少人都在使用框架,即便你不使用 Vue,也可能使用 React、Angular 或其餘框架。
很難想象,在沒有這樣工具的狀況下就去構建一個複雜的前端應用程序。
固然,你仍然能夠使用普通的 JavaScript 去作這些事,只是那樣將花費咱們更多的時間。
我猜當大多數人在面對這些框架的時候,會疲於對這些框架進行比較。
每當媒體給我推送關於框架比較的文章時,好比《2019最好用的7個新框架》,我一般會說:「咦~」
這不是由於說:「啊,我寫了 Vue,我想讓人用它,我不想聽到有人說它的壞話」
而是由於大多數時候,這些文章只關注 github 的 star 數,npm下載量,stackoverflow 問題統計等這些能夠隨時隨地經過 Google 查找到的內容。
可是,這些統計數據在某種程度上仍是有用的,好比對於市場營銷來講。
可是若是你嘗試去作一個技術決策,而且嘗試去和市面上已經成熟的技術去競爭的話,那麼這些數字在某個閾值上的相關性會愈來愈小。
好比,咱們在生產環境使用的東西,你知道的大部分可能都過了 10000 個 star 了。
但這個門檻真的那麼重要嗎?一個庫到底有幾千 star?
這並不重要,相反你應該更關心的是一些內部技術決策,好比致使這些框架的延遲發佈的真實緣由是什麼。
因此在咱們深刻研究以前,咱們先退一步思考下全部的這些框架的共同目標,咱們都在努力實現的同一目標。全部框架的做者們都在朝着「讓大家儘可能能更高效地構建 Web 應用程序」這一目標而努力,那麼爲何咱們還要有這些不一樣比較的競爭的想法呢,這究竟是好仍是壞呢?
因此爲何咱們有這麼多不一樣的框架,並且每一個框架都有不少的追隨者呢?
就像 React 和 Angular 各自都有超過 50 萬的用戶。
我認爲不能單純的以一個好與壞來評價一個框架。
人們每每會問一些問題,好比哪一個框架更好,請別再問這個了。
由於咱們很難簡單地去評定一個框架要優於另外一個框架。
咱們都知道軟件設計在於取捨,事實上咱們如今的前端框架設計有太多的地方須要進行取捨,尤爲是在 Web 中。
由於 Web 是一個充滿多樣化元素的平臺。
咱們能夠在 Web 上構建各類有趣的事情,不管是最簡單的頁面仍是到你所天天使用的複雜程序。
所以,爲了適應全部這些狀況,框架制定者必須在多方面進行取捨。
今天我會將其中的一些拿出來聊聊,但願能對你在這塊的見解有所幫助。可是因爲時間緣由,我確定不能很是深刻的去講解每種狀況。
因此,我只會專一其中的一部分。
第一:職責範圍。從本質說是指這個框架能夠爲你作多少事情。
第二:渲染機制。當你在使用一個框架的時候,你會如何表達你的視圖層,框架如何處理代碼?它是如何將實際渲染東西展現到頁面上的?
第三:狀態機制。可變和不可變,髒檢查和依賴追蹤,響應式和類響應式。實際上,我沒有時間去深刻研究這個,這個或許能夠在下次分享中好好談論下。
此次,我深刻探討下職責範圍。看看一個框架能爲咱們作什麼事情。
咱們將它一分爲二,從大家的角度來看,這個框架或庫能作一些特有的小事情,從咱們的角度來看,咱們會有不少總體性的考量,拿框架來講,我會盡可能提供儘量多的特性。
舉一些你們可能比較熟悉的表明性的例子,React 接近於原生庫,Angular 則提供更多抽象概念。
不多有人會去說清楚原理,這個庫(React)專一於提供一個很是基礎的 UI 模型,它專一於提供更底層的原生實現,基於此你能夠構建出一套屬於本身的抽象。
有意縮小職責範圍(設計理念),這也是React整個生態系統很是活躍的緣由所在,React的社區環境就像個商城(系統),圍繞着 React 的核心模型自底向上創建起來的一整套生態系統。
另一方面,像 Angular 以及其餘的一些框架,如 Ember、 aralia 這種,則更像是大教堂吧。
它們則是自上而下進行設計的,在設計過程當中,用戶可能會遇到的問題都被考慮在內。
例如大家在平常開發中會常常遇到的表單驗證,動畫效果等等。
爲了讓框架能夠給咱們提供一個解決方案,在這個框架設計之初,咱們就要以自上而下的方式來對它進行設計,即咱們須要去思考如何將全部事情放到一塊兒去工做。
有意擴大職責範圍(設計理念),這個設計理念就是當你嘗試解決一個問題時,你在框架內就能找到解決方案。
咱們把這稱之爲大小職責範圍(這裏指兩種設計理念),而這也沒有好壞之說。
我想再次強調下。
小的職責範圍(設計理念)它的好處在於,剛開始的時候須要理解的概念不多。
並且它具備更好的靈活性。因爲框架、庫只提供了部分底層的原生實現,因此當你須要一個組件類的話,它得有一些 Props,而後你能夠經過 Props 來傳遞數據,返回 VDOM 節點。
最重要的是,你能夠構建任意複雜的系統。
React 有一個很是活躍的生態系統,咱們能看到它擁有一些很是靈活的工具,而後,咱們能夠基於它們發揮出更大的創造力,而這些很棒的想法都來自 React,React 社區。
另外,有意縮小職責範圍,也可讓團隊擁有更小的維護層面,以便他們能夠專一於他們認爲重要的事情。
這樣團隊能夠專一於探索一些比較有創意的點子,這也是爲何 React 能夠花這麼多時間來作 concurrent mode、suspense、React Hooks 以及在過去幾周或幾個月內一直在創造的全部的這些有趣的東西。
實際上他們在這些事情的開發上已經花了好幾年了,只不過由於它們的粒度比較小,正是由於這樣他們才能更加專一於這個事情上。
固然,小範圍的設計也是有一些明顯的缺點的。
首先第一點,當你想用一個簡單的概念去解決一個原本就很複雜的問題的時候你須要作更多的鑽研工做。
我特別喜歡 Steele 這個傢伙在一場演講中說的一句話:「培養一種語言」。在演講期間,他給本身制定了一條規則,他在演講期間必須使用單音節詞,若是你想用任何相似於多音節詞的話,他必須先用單音節詞來定義它。
他只有很是有限的、很是原始的一些東西,去構建一些複雜的想法。
因此你能夠想象一下那次演講是怎麼回事。
在他每次想要說出本身喜歡的一句話以前,他都要翻出一些幻燈片而後找出一堆單詞,而後繼續。這有點像用很是低級的原始語言去構建一個很是複雜的生產級別的應用程序。
你必須構建大量的抽象概念,以便在此過程當中提升本身的效率。
正由於如此,模式天然會隨着時間的推移而出現。
當咱們說 React 是真的容易上手的時候,咱們是否有些忽略了你或多或少須要學習 Redux 的事實。在你認爲本身是一名真正的 React 開發人員以前,你必須先去了解 HOC 高階組件、render props。而後如今,你又要去學習 Hooks 以及在 JS 中使用 CSS 的各類方式。
儘管這些模式隨着時間的推移而出現,但它們卻變成了半須要的狀態。若是你不瞭解這些,你真的能夠稱本身是一名 React 開發人員嗎?
而這些東西每每沒有官方文檔。若是你去 React 官方網站,它是不會告訴你某個 CSS 和 JS 的解決方案的,你必須本身去研究並學習它。
這就是爲何使用者真的須要有自主學習能力的緣由所在。
現現在,生態系統發展太快可能會致使碎片化和使用者的不斷流失。我相信早期 Flux 思想的追隨者,會發現天天都有一個新的 Flux 方案具體實現,而後每一個 Flux 的具體實現都會對應新的 CSS/JS 的實現。
這樣很好,同時好處就是總會有新的想法出現。一樣,咱們也在努力尋找最佳方案。
可是,這對於那些只想跟在後面去使用的人來講是很差的,你會不斷的有FOMO思想(Fear of Missing Out,懼怕錯過),老是怕錯過下個最好的東西。
咱們已經說完了小職責範圍(設計理念)的缺點。如今讓咱們來談談大職責範圍的一些優勢。
最明顯的優勢是能夠經過構建抽象概念來解決最多見的問題。
若是你只是想作一些開發,我只須要一個路由、一些動畫以及一個 HTTP 客戶端來獲取一些數據。
像 Angular 這樣的框架則提供了全部你須要的東西,來實現這一目標。
事實就是你沒必要處處查資料,你只要照着它的文檔去用框架,你就能夠搞定這些事。
集中式的設計確保了它自己與其生態系統的一致性。
當你遇到一個具體問題的時候,你沒必要去找一些不一樣的解決方案,你只須要看看框架它讓你作什麼,最大的可能就是它(框架)對此已經有解決方案。因此你壓根沒必要去挖掘所謂的10種不一樣的解決方案,而後找出對你案例最佳的那一個。
如今來講下缺點,這樣的缺點就是會有一個更高的學習門檻。
爲了將一個像素放到屏幕中,你必須跳過一些步驟才能作到,這對於初學者來講是一個很大的障礙。對於那些不適應的人,我這裏不說那些適應的人哈,若是你沒有相似使用 Java 或者 C# 等語言經驗的話,而是僅僅只學過 HTML/CSS 以及 JavaScript 的話,當你看到 Angular 文檔的時候,你可能會以爲有點難以想象。
對我來講也是如此。
而後,若是內置的解決方案是不適合當前用例的話,它則會變得不靈活。有時候你可能以爲我只是想用另一種方式來作,可是我卻沒方法來將其替換。
最後,一個職責範圍大且成型的框架會使得引入一些底層新想法的成本更高,由於太多的地方都要保持其一致性。
而後當你想嘗試用一個底層想法的時候,它會影響到你項目中的每一個組件(牽一髮而動全身)。
因此要作這種 「改變」,就變成了一件很困難的事情。而若是你在 React 的生態系統中說,我引入 Hooks 會讓 Redux 更加冗餘,那麼朋友,這並非一個真正的問題,由於 React 它的核心團隊實際上並不會負責這些解決方案。
就是這樣,okay。
這正是 Vue 所處的位置。但在咱們深刻了解 Vue 如今正在作的事情以前,我想強調的是,我並非說 Vue 比這兩個框架都好。
由於處於中間位置不必定就是最好的。若是 NG 和 React 在某個功能的封裝程度上差別很大,Vue 要作的就是去縮小差別,而後你會發現實際上 Vue 並無作到最佳。
因此,這就好像咱們稍微推遲去尋求咱們所認爲的最佳平衡點。而每個選擇都會適用於不一樣人羣的須要。
它並不像一件東西同樣,能夠適用於全部人。
因此我所說的 Vue 在職責範圍這個問題的處理方式上,你可能知道咱們都叫 Vue 是一個漸進式框架。
職責範圍漸進意味着框架使用分層設計,它容許以漸進的方式選擇特性。也就是說,若是你不須要路由,若是你不須要狀態管理,甚至若是你不須要構建步驟。你能夠使用沒有任何特性的 Vue,你只須要將 vuejs 拉到你的頁面中,而後你就能夠當即開始作一些事情。
對於初學者來說,一個須要翻越的學習障礙,就是剛開始學習時就要求你從屏幕中獲取一個像素並移除它。
因此,低的學習門檻對咱們來真的很重要,這也是 Vue 的一個使命:容許更多的人蔘與 Web 開發,容許人們學習它(Vue)並專一於開發,而不是讓你學習一堆在你當前開發可能不須要的概念。
可是對於當前的這些問題,咱們仍然有經過文檔去提供解決方案。當你的用例變得更復雜的時候,當你要構建更復雜的東西的時候,這時你意識到本身須要一個路由。而後你就開始翻閱文檔,你會發現,okay,我確實能夠使用路由去作這個。
但與此同時,路由它又並非必需的。而且,若是你願意的話,你本身也能實現一個路由,由於你能看到 Vue 的路由是如何構建的,而且它的核心實現是很是乾淨的, 因此若是你願意的話,是能夠用本身的方式去構建一個的。
它並不完美,由於做爲中間者,咱們須要去權衡二者的利弊。
因此首先,儘管咱們會採用新增模塊(集成 router、vuex 等),但咱們仍然須要負責維護它們(router、vuex 等)
因此,咱們分享了大職責範圍下統一維護面的問題,咱們要想從根本上改變一些東西,咱們必須確保整個生態系統的一致性。
這個維護負擔幾乎與大職責範圍相同,同時也由於咱們提供了這些預置的解決方案。
咱們的生態系統可能不會像小職責範圍那樣多樣化。由於小職責範圍喜歡把問題拋給社區。而在咱們的案例中,不少用戶很滿意咱們的解決方案,同時本身也不用再花費時間去找答案。
這就是職責範圍的問題,但願你如今已經有所瞭解了,我認爲這就是 React、Vue 和 Angular 之間最根本的區別。
這是它的準肯定位,也定義了咱們不一樣的用戶羣。
不少時候,咱們都是在有意決定所擴展的領域。做爲框架設計者,咱們知道咱們正在駕馭不一樣的領域。這是件好事,由於在整個階段,不一樣的開發人員須要不一樣的解決方案,以及擁有覆蓋整個主要框架的規範,確保每一個人都獲得他們想要的。
OK,如今咱們來談談渲染機制。
也就是說你該如何經過框架來表現本身的UI結構以及該框架是如何進行渲染的。
首先,從操做層面來說它真的很複雜,它不只僅是一件事,它包含了不少層面。
簡單點來說,能夠將它當作 JSX 與 Templates,即動態渲染函數和基於靜態字符串的複雜的 Vue 表達式。而後就是表現力和原生性能,以及運行時調度和提早優化。
有些人對此會有很強烈的意見,但我我的認爲他們本質上是很類似的,他們只是對同一個底層理念的不一樣策略表達。
能夠說更多的是技術上的權衡。
一方面,固然是 JSX React 以及全部使用 VDOM 的 react-like 庫,好比 pre-act、 stencil, infernal 等。
另外一方面,則是基於模板的解決方案。我稍後會討論 Vue,但更具表明性的基於模板的解決方案有 Svelte,還有就是 ember。
能夠看到,那個 logo 其實是 glimmer.js 的 logo,也就是說,glimmer 是 Ember 裏的渲染引擎,一樣也是 Angular 的渲染引擎。
這些主要是基於模板的,它們將模板編譯成相對較低級別的指令來進行內容渲染。
如今咱們來談談 JSX 和 VDOM 的一些優勢。
咱們喜歡 JSX 或 VDOM 最重要的緣由就是它們具備 JavaScript 的完整表現力。
你無須在乎語法,你有一種可供你使用的語言,你就能夠有完整的體驗,你能夠作任何你想作的事。
不只這樣,你還能夠在你的組件上構建任意複雜的邏輯。
它真的很強大、不作約束,也由於這個特色,不少人喜歡上了 React 。
它還容許你在渲染組件時將視圖層視爲數據。它會返回一些東西,返回節點表示當前狀態的VDOM 節點,這個數據能夠用於不少有意思的地方。
它對於咱們構建測試方案頗有用,你能夠根據虛擬Dom獲取快照,你能夠將它渲染到須要替換的目標,也就是咱們一直在作的事情,好比將它渲染到終端、PDF、Canvas、WebGL,以及任何你能想到的你能夠渲染的東西。
由於視圖就是是數據,而你能夠對數據作任何操做。
目前,VDOM 自己成本真的很高。
想想,當咱們剛出來的時候,不少人都認爲,這不是很慢嗎?答案是 Yes,咱們很慢,但速度卻足夠快!
可是,仍然從純粹的技術角度來看,你作了不少多餘的工做。想一想這個簡單的模板,它只須要更新其中單個消息綁定就能夠完成大量的工做。
咱們必須遍歷整個 VDOM 節點而且作 Diff,在這個過程當中,一直以遞歸的方式向下傳遞,直到你以某種方式更新它。
所以,標準 VDOM 不一樣的代價是相對於視圖的總大小,而不是可能改變的節點數量。
即便你只有一個節點,也可能會觸發 這個VDOM 的 Diff 算法。
正是因爲渲染函數的動態特性使得它難以優化。
關於動態性,個人意思是你能夠寫這樣的代碼。
你能夠使用一個 for 循環來構建一個 children 數組,而後將它交給你的父節點,以及接下來進行你想要作的其餘事情,也就是說你能夠先建立一個父節點,而後經過往它的 children 中添加元素來進行改變。
你在使用 JavaScript 的時候,編譯器不可能hold住全部可能發生的事情,由於 JavaScript 太過於動態化。
在這塊咱們已經作了不少嘗試,但從本質上來講,咱們很難經過這種方式對其提供安全的優化。
由於它不是你簡簡單單作足夠多的條件預斷就能夠的,你對用戶意圖作的預判越多,代碼越容易優化,這對於Javascript來說實在太難了。
最後,React 對於這塊的解決方案就是不把重心放在加快 VDOM 自己的速度,而是如何提升感知性能。
所以,React 引入了運行時調度併發時間切片的概念,可是這種運行時調度方案,整個 fiber,幾乎和咱們管理本身的堆棧同樣,好比進入和退出渲染,全部的東西都須要很長的運行時間。
這意味着不管你什麼時候加載 React,都必須去加載那些用於處理複雜的運行時調度工做的全部必需代碼。
這就像加載幾個20、30KB 大小的 JavaScript 同樣。
反過來,這也會讓你的初始化加載受到一點影響。
另外一方面,若是你是在模板中編譯的渲染代碼,一般它能夠生成一個更加直接的渲染指令,而且具備更好的原生性能。緣由就是:根據定義,模板是一種很是有約束的語言,你只能以某種方式去編寫模板。
例如,當你寫出這樣的代碼的時候,咱們能夠馬上告訴你,這些 p 標籤的順序是不會變的,這個 id 是不會變的,這些 class 也不會變的,惟一會變的就是這個。
靜態(編譯)和很是嚴格的限制其實是容許編譯器對你的意圖作更多的預判,從而給它更多的空間去作執行優化。
咱們來看看 SVELTE 編譯代碼時會作什麼。
其餘全部內容都是靜態的,只有 name 可能會發生改變,這個 p 是一個 update 函數,它惟一作的事情就是當 name 發生變動的時候對它(name)進行更新。
將 SVELTE 與 VDOM Diff 算法所作的事情相比較的話,它只有到達必定量級纔會更快。
因此說,根據策略的不一樣,模板編譯或者基於通用編譯的方法也能夠使 runtime baseline 更輕量,由於它不須要全部的複雜運行時調度來嘗試讓事情看起來更快,由於它自己已經很快了。
因此 SVELTE 能夠產出一個很是輕量的輸出,而不須要一個很重的 baseline runtime 來適應全部可能的 runtime 行爲。
如今來看看模板編譯的缺點。很顯然,你會受限於模板語法,從而失去 JavaScript 的表達能力。
因此,當你想去構建一個真正複雜的組件的時候,你會想我要能夠在模板裏這樣作多好,然而編譯器對此並不支持。
很不走運,若是你選擇完整的編譯路線,那就沒有退路,由於級別越低的編譯輸出,實際上你越難將你的自定義操做與它進行掛鉤。
就比如 opa 編譯器,你是沒法深刻到彙編去看看爲何會這樣,就比如你沒法使用 C 語言去調試你的彙編代碼。
更輕量的 runtime、更輕量的 baseline runtime,也多是以每一個模板更詳細的輸出做爲代價。由於當你試圖去生成儘量高效的代碼時,有時你必須直接在輸出的時候編碼更多信息。
例如,SVELTE 生成的代碼實際上是以命令式的形式經過逐行插入建立了全部元素,而且它們有一個單獨的函數進行更新操做。
相比之下,基於 VDOM,結果是你只須要一行,而這(一行)只是一個返回 VDOM 結構的表達式。
若是在運行時編譯,則會產生運行時編譯成本。
所以,對於生產用例來講,最有可能的狀況是你須要用戶事先編譯,這樣對於構建步驟來講是一個硬性要求,這是不可避免的,要麼在運行中進行編譯,要麼在預構建中進行編譯,其中涉及咱們如今或多或少習慣的全部node.js工具鏈。但若是你能避免的話,對於初學者來講是件好事。
OK,所以,Vue 又一次夾在中間,我想再次強調,這不是說 Vue 是最好的。
可是,Vue 的渲染機制獨特之處在於,若是你真的將模板結合到 VDOM 中,那麼咱們能夠同時擁有 VDOM 和模板編譯。
因此咱們能夠充分利用這兩點。
咱們有作過性能測試:在編譯步驟中產生的特別優化,咱們不作渲染功能,稍後我將詳細介紹這一點。
在 vue2.x 版本,咱們實際上尚未充分利用這個機會,當前 vue 2.x 中的 VDOM 性能這塊表現平平。
但我會談下 3.0 對這點所作的事,讓它能夠更快。
還有表現力,你能夠跳過模板層直接進入渲染函數,直接利用JavaScript來執行任意複雜的邏輯。
所以,當你感受本身受到模板約束時,這會爲你提供一條出路。
缺點是,儘管咱們如今確實很快,咱們可能永遠不會比 SVELTE 感受起來快。由於 SVELTE 的輸出是最普通的 JavaScript。然而,爲了兼容手寫的渲染函數,Vue 仍然須要維護 VDOM,這樣一來常量則必不可少。另外一方面,它也會產生分歧,即我到底應該使用哪種方式?
所以,不少用戶雖然能夠使用渲染函數,但他們可能從未使用過它。
如今讓咱們把它放到咱們經過文件作的事情上,將 Vue 的模板編譯成 VDOM,其運行速度比普通的 VDOM 要快。
這就是咱們剛纔已經討論過的,這個模板只有一個節點會改變。理想狀態下咱們只需直接更新 message 字符串,節點結構是靜態的,而且歷來不會發生變化,只有一個動態節點。
因此,若是咱們研究這個模板能夠看出它是個很是簡單的例子。
當咱們有相似於 v-if 這樣的東西時,它會變得有點複雜,咱們稱之爲 JSX 中的結構指令,它至關因而根據條件返回不一樣結果判斷的三元表達式。
如今,這會建立一個動態節點結構,由於該節點可能存在或可能不存在。
爲了處理這種簡單的 VDOM Diff 算法,假設節點列表已經改變,那麼咱們須要對兩個子數組進行 Diff 操做。
可是若是咱們嘗試將其拆分,會看到 v-if 將模板拆分爲兩個嵌套塊。
咱們來思考一下,若是將 v-if 自己看做一個節點,外部塊則會有一個靜態節點內容、節點結構。
在 v-if 內部,它也是靜態的。咱們有兩個靜態塊,在每一個塊內,你無需對節點順序進行 Diff 操做,你惟一要作就是這個塊內部進行數組的扁平化操做。
同理,對於每一個 v-for 迭代咱們也能夠將其當作一個靜態塊。
所以,若是你有更多像 v-if 、內嵌 v-for 的寫法,你只是在進一步將代碼拆分紅嵌套塊。
因此,咱們最終獲得一種我稱之爲 Block Tree(區塊樹)的東西,這只是一種玩法。
但 Block Tree 是一個嵌套塊的塊列表,由於每一個塊中都有一個徹底靜態的節點結構,全部沒有必要使用遞歸到下層去對子列表進行 Diff 操做。
在每一個塊中,你只有一個單一扁平化數組節點可能會發生改變,咱們還提供了其它組織上的提示。例如,若是一個節點只有一個動態 class 綁定,咱們有條捷徑,即你只需直接設置 class,而後就能夠繼續執行,而沒必要對 Props 進行 Diff 操做。
因此,對於同一模板的 Diff,vue2.x 版本和 vue3.x 版本的作法會有明顯的區別。vue2.x 版本咱們須要作一個完整的 Diff 操做,vue3.x 版本咱們就只需經過使用一個單一扁平化數組(包含一個動態文本節點),而你惟一須要作的事情就是比較文本是否發生了改變。
對此,咱們作了一個簡單的基準測試(benchmark), 作 1000 個 v-for 列表迭代,每一個塊有 12 個 dom 節點,總共 12000 個 dom 節點,每次迭代都會動態綁定一些類或者文本。
而後咱們在頁面上作了 4000 個動態綁定,而後對其更新。咱們作了 100 次運行,在目前 2.6 的版本,更新時間要 36ms,而在目前 3.0 的版本中,使用新的編譯策略,只須要大概 5.4ms,比以前快了6倍多。
注意,(數據)僅限於這個基準測試。真實的應用中你可能會有一個不一樣的數字,但或多或少,它都會更快,這是一個基準。
而後,在狀態機制這塊,我可能沒有時間去真正深刻研究這個問題,它可能會是另一個演講的話題。
可是仍是總結一下,當你試圖去設計一個框架時,最佳平衡點在哪?
或許這個問題應該從新表述下。是否存在一個完美的平衡點?它又是不是一個單一的完美的平衡點,甚至是以 JS 開發人員做爲一個總體的最佳平衡點?
由於像咱們全部人同樣,都在努力去優化咱們正在構建的一些特定又不一樣的東西。
好比說 SVELTE,它的優點在於當你構建一些小的東西時,它能夠產出很是輕量級的代碼。它也很是快,消耗內存也很是少,因此它甚至能夠像嵌入式設備同樣使用。
可是若是在你本身的使用場景中,你可能會有一個更復雜的實現,你會有更多的組件,你想要 JavaScript 的表現力,同時你也須要模板提供更多的性能,那麼(這種場景下)你能夠使用 Vue。若是你不是很在乎一些極端的性能,而後說我就是喜歡 React 的生態系統,那麼你能夠使用 React。
你也能夠選擇全部這些(框架)。我認爲這樣很好,框架領域能像一個多維空間,有多個不斷變化的實體,就像把每一個框架都想象成一個試圖尋求平衡點的實體。相信咱們老是會有不少人去努力找出什麼是最佳的作事方式。
做爲一個開發人員,你可能會在這些實體之間遊移不定,而後你可能會被其中的一個吸引過去,有時你有可能只是在周圍跳來跳去,而後試着去找出最適合你的一個。我認識這是件好事。
可是做爲一個使用者,嘗試在這個多維空間中找到正確方法是很是困難的。
可是若是你想正確的選擇框架,難的就是你必須瞭解框架所作的一些內部權衡,你必須知道這個框架朝着哪一個方向發展,而且知道它與你構建的東西是否一致。
但願經過此次演講所闡述的話題可以幫助到你,即當你嘗試在將來選擇框架、或者當你告訴別人應該如何選擇框架時,能給予你幫助。
謝謝。