大家好,我是若川。今天分享一篇框架設計思路的好文。

關于我
大家好我是花果山的大圣,今天很榮幸,有機會跟大家分享一下很多年輕人感興趣的話題《 Vue 和 React 設計思想 PK》,個人水平有限,如果有理解不到位的請傾盆,大家看完后并且再去 Vue 和 React 源碼里探索一番,一定會有所收獲, 如果沒時間的話,還可以跟我一起早起學習
Github
B站
掘金


框架總覽
前端框架繁多,在學習的時候也會陷入困惑,我們應該抓住最主流的內容 Vue/React,深入底層,嘗試揣摩框架作者的設計思路,開闊自己的視野,大家也不要把自己限制在框架之中,認為工作中用到 Vue,就覺得 React 學起來沒用,有些時候我們學習競品的框架,是為了更好的認識自己在用的框架,廢話不多說,由于 Vue 本身是個中庸的框架,再揪出設計思路理念比較極致的 Angular 和 Svelte,我們先從視圖層最火的四大框架看一下

下載量

對比維度
我們從多個維度去對比前端的框架,就能看清楚現在各個框架的現狀,我們學習每個框架的設計范式,并且嘗試打破局限,就像豬八戒一樣,出了高老莊,一路好風光


框架發展
字符串模板
想看清現在視圖層的現狀,要簡單的看下之前框架的發展路線,JQuery 時代的渲染層,大部分都是基于字符串的模板,典型的框架就是 Underscore,baiduTemplate。大致的原理就是把 template 解析成一個函數,缺點也很明顯,就是每次數據變化,模板內部要全部重新渲染


然后剛才我說的四個框架占領了現在的 Web 領域,核心的目標都是一樣的,為了做出性能更好的 Web 應用,為此各路大神八仙過海,各顯神通有這么幾個宏觀的維度
原生 VS 抽象
原生的就是 JavaScript 本身,比如 JQuery 基本沒有太多的抽象,一個 $ 打天下,React 抽象程度稍微復雜一些,需要理解 Component, State, Hooks, JSX 等概念就可以上手了,抽象比較多的就是 Angular,上手就需要了解十幾個概念,學習曲線很陡峭, Vue 就處在 React 和 Angular 中間,了解完 data,methods,單文件組建后就可以上手了

運行時 VS 預編譯
另外一個維度就是運行時和預編譯這個維度,所謂運行時,在瀏覽器內存里進行的任務,React 的 Runtime 比較重一些,數據發生變化后,并沒有直接去操作 dom,而是生成一個新的虛擬 dom,并且通過 diff 算法得出最小的操作行為,全部都是在運行時來做的
這個維度的另外一個極端,也就是重編譯的框架,在上線之前經過通過工程化的方式做了預處理,典型代表就是Svelte,基本上是一個 Compiler Framework,寫的是模板和數據,經過處理后,基本解析成了原生的 dom 操作,Svelte 的性能也是最接近原生 js 的


Vue 依然處于比較中庸的地位,在運行時和預編譯取了一個很好地權衡,保留了虛擬 dom,通過響應式控制虛擬 dom 的顆粒度,在預編譯里又做了足夠多的性能優化,做到了按需更新,這個一會再細聊
框架設計的維度
Vue 和 React
然后我們揪出來 Vue 和 React,有一些更細化維度

可變數據 VS 不可變數據
Vue1 就是把響應式數據玩出了花,通過攔截操作,修改一個數據的同時收集依賴,然后數據修改的時候去通知更新 dom,體驗很是舒爽,我們修改了一個 JavaScript 的對象,視圖層就修改好了, 這是 Vue 的黑魔法,React 的虛擬 Dom 創建之日期,就是通過計算新老數據的 diff,去決定操作那些 dom,所以每次修改數據,需要生成一份新的數據,說不上優劣之分,只不過路線不同

這大概就是 Vue 和 React 修改數據的代碼對比



權衡
隨著應用越來越復雜,React15 架構中,dom diff 的時間超過 16.6ms,就可能會讓頁面卡頓,Vue1 中的監聽器過多,也會讓性能雪崩,為了解決這個問題,Vue 選擇了權衡,以組件作為顆粒度,組件層面用響應式通知,組件內部通過 dom diff 計算 ,既控制了應用內部 Watcher 的數量,也控制了 dom diff 的量級。看到這段實現的時候,不僅高呼,真是妙啊

??registerComponentHook(componentId,?'lifecycle',?'attach',?()?=>?{callHook(vm,?'beforeMount')const?updateComponent?=?()?=>?{vm._update(vm._vnode,?false)}new?Watcher(vm,?updateComponent,?noop,?null,?true)vm._isMounted?=?truecallHook(vm,?'mounted')})
預編譯和運行時
相關概念剛才已經科普了,在 Vue 和 React 中的體現,主要體現在 JSX 和 template 的區別上,React 是完全的 JSX,可以 JSX 在里面寫 JavaScipt,所以特點就是足夠的動態,與之對應的就是 Vue 的 template,template 的特點是語法受限,可以執行的語法技術 v-if
v-for
等指定的語法,雖然不夠動態,但是由于語法是可便利的,所以可以再預編譯層面做更多的預判,讓 Vue 在運行時有更好的性能
順便放兩張尤大的 ppt 的圖,Vue3 通過在預編譯階階段做靜態標記的優化,做到了按需更新
純靜態的元素標記,直接越過 diff 階段 ?比如
<p>hello</p>
靜態的屬性也會標記,在 diff 的時候越過這個屬性的判斷
事件函數傳遞的時候回加上緩存
v-if
和v-for
內部通過 block+ 數組的方式維護動態元素






時間切片
Vue3 通過靜態標記 + 響應式 + 虛擬 dom 的方式,控制了 diff 的顆粒度,讓 diff 的時間不會超過 16ms,但是 React 自上而下的 diff 過程,項目大了之后,一旦 diff 的時間超過 16.6ms,就會造成卡頓,對此 React 交出的解決方案就是時間切片
簡單的來說就是把 diff 的任務按照元素拆開,利用瀏覽器的空閑時間去算 diff,React 把各種優化的策略都留給了開發者,Vue 則是幫開發者做了很多優化的工作




設計思想演進
組合優于集成
這個思想設計模式里面就有定論,也是現在 hooks 和 composition 大行其道的原因,代碼寫出來也會更加易于維護,這個圖可以很好地體現出可維護性上的變化

跨端
剛才我們講了 Svelte 可以做到直接編譯成 JavaScript,性能接近原生,這么優秀的思想,為什么 Vue 還要保留虛擬 dom 這個額外的 runtime 損耗呢,我覺得比較重要的一個答案就是跨端
虛擬 dom 除了可以用來計算最小的 diff 之外,另外一個重要的功能就是可以用 JavaScript 的對象來去描述一個 dom,這就是一個普通的對象,在跨端領域意義重大,視圖層返回的是一個對象,渲染層可以調用不同平臺的渲染 api 去繪制即可

復習
如上所述,請認真學習框架,并不只是為了面試,而是框架里的優秀思想和設計模式,匯集了頂尖開發者團隊最優秀的思想, 多學習別人優秀的代碼,開闊自己的視野, 閉門造車你會發現,很多自己的頓悟只是別人的基礎


推薦書
最后推薦一本對我漲薪幫助最大的書《算法》第四版
算法和數據結構一直都是前端工程師進階的攔路虎之一,這塊內容比較成體系,JavaScript 相關的算法書過于簡單,只能入門,不能幫你學會算法, 教材《算法導論》從數學的角度去推導算法,又太難,所以我推薦這本《算法》第四版,內容詳實有插畫,幫助系統的構架算法知識體系,書里用的是 Java,學習的時候正好用 JavaScript 實現一遍書里的例子,學完絕對是一個新的段位
當然,我最大的愛好除了王者,就是看書了,其實有很多書可以推薦,比如
JavaScript 進階的紅黃綠三套書
怎么和 HR 談錢的《談判是什么》和《優勢談判》
和產品經理吹牛逼必備壇子 《浪潮之巔》《硅谷之謎》
《軟技能2》
。。。。
以后有機會再給大家推薦,感謝大家的支持 ,我是大圣, 下期再見
常駐推薦閱讀
若川知乎高贊:有哪些必看的 JS庫?
我在阿里招前端,我該怎么幫你?(現在還可以加模擬面試群)
如何拿下阿里巴巴 P6 的前端 Offer
如何準備阿里P6/P7前端面試--項目經歷準備篇
大廠面試官常問的亮點,該如何做出?
如何從初級到專家(P4-P7)打破成長瓶頸和有效突破
若川知乎問答:2年前端經驗,做的項目沒什么技術含量,怎么辦?
常駐末尾
你好,我是若川,江西人~(點擊藍字了解我)歷時一年只寫了一個學習源碼整體架構系列?有哪些必看的JS庫:jQuery、underscore、lodash、sentry、vuex、axios、koa、redux
關注
若川視野
,回復"pdf" 領取優質前端書籍pdf,回復"1",可加群長期交流學習我的博客地址:https://lxchuan12.gitee.io?歡迎收藏
覺得文章不錯,可以?分享、點贊、在看?呀^_^另外歡迎
留言
交流~
小提醒:若川視野公眾號面試、源碼等文章合集在菜單欄中間
【源碼精選】
按鈕,歡迎點擊閱讀,也可以星標我的公眾號,便于查找