為什么 ReactJS 不適合復雜的前端項目?


問題一:ReactJS組件難以在復雜交互頁面中復用

ReactJS中的最小復用單位是組件。ReactJS的組件比AngularJS的Controller和View 要輕量些。 每個組件只需要前端開發者提供一個 render 函數,把 props 和 state 映射成網頁元素。

這樣的輕量級組件在渲染簡單靜態頁面時很好用, 但是如果頁面有交互,就必須在組件間傳遞回調函數來處理事件。

我將在《More than React(二)組件對復用性有害?》中用原生DHTML API、ReactJS和Binding.scala實現同一個需要復用的頁面,介紹Binding.scala如何簡單實現、簡單復用復雜的交互邏輯。

問題二:ReactJS的虛擬DOM 算法又慢又不准

ReactJS的頁面渲染算法是虛擬DOM差量算法。

開發者需要提供 render 函數,根據 props 和 state 生成虛擬 DOM。 然后 ReactJS 框架根據 render 返回的虛擬 DOM 創建相同結構的真實 DOM.

每當 state 更改時,ReacJS 框架重新調用 render 函數,獲取新的虛擬 DOM 。 然后,框架會比較上次生成的虛擬 DOM 和新的虛擬 DOM 有哪些差異,然后把差異應用到真實DOM上。

這樣做有兩大缺點:

  1. 每次 state 更改,render 函數都要生成完整的虛擬 DOM. 哪怕 state 改動很小,render函數也會完整計算一遍。如果 render 函數很復雜,這個過程就白白浪費了很多計算資源。
  2. ReactJS框架比較虛擬DOM差異的過程,既慢又容易出錯。比如,假如你想要在某個 <ul>列表的頂部插入一項 <li> ,那么ReactJS框架會誤以為你修改了 <ul> 的每一項<li>,然后在尾部插入了一個 <li>

這是因為 ReactJS收到的新舊兩個虛擬DOM之間相互獨立,ReactJS並不知道數據源發生了什么操作,只能根據新舊兩個虛擬DOM來猜測需要執行的操作。 自動的猜測算法既不准又慢,必須要前端開發者手動提供 key 屬性、shouldComponentUpdate 方法、componentDidUpdate 方法或者 componentWillUpdate 等方法才能幫助 ReactJS 框架猜對。

我將在《More than React(三)虛擬DOM已死?》中比較ReactJS、AngularJS和Binding.scala渲染機制,介紹簡單性能高的Binding.scala精確數據綁定機制。

問題三:ReactJS的HTML模板功能既不完備、也不健壯

ReactJS支持用JSX編寫HTML模板。

理論上,前端工程師只要把靜態HTML原型復制到JSX源文件中, 增加一些變量替換代碼, 就能改造成動態頁面。 理論上這種做法要比Cycle.js、Widok、ScalaTags等框架更適合復用設計師提供的HTML原型。

不幸的是,ReactJS對HTML的支持殘缺不全。開發者必須手動把classfor屬性替換成classNamehtmlFor,還要把內聯的style樣式從CSS語法改成JSON語法,代碼才能運行。 這種開發方式下,前端工程師雖然可以把HTML原型復制粘貼到代碼中,但還需要大量改造才能實際運行。 比Cycle.js、Widok、或者、ScalaTags省不了太多事。

除此之外,ReactJS還提供了propTypes機制校驗虛擬DOM的合法性。 然而,這一機制也漏洞百出。 即使指定了propTypes,ReactJS也不能在編譯前提前發現錯誤。只有測試覆蓋率很高的項目時才能在每個組件使用其他組件時進行校驗。 即使測試覆蓋率很高,propTypes仍舊不能檢測出拼錯的屬性名,如果你把onClick寫成了onclick, ReactJS就不會報錯,往往導致開發者額外花費大量時間排查一個很簡單的bug。

我將在《More than React(四)HTML也可以編譯?》中比較ReactJS和Binding.scala的HTML模板,介紹Binding.scala如何在完整支持XHTML語法的同時靜態檢查語法錯誤和語義錯誤。

問題四:ReactJS與服務器通信時需要復雜的異步編程

ReactJS從服務器加載數據時的架構可以看成MVVM(Model–View–ViewModel)模式。 前端工程師需要編寫一個數據庫訪問層作為Model,把ReactJS的state當做ViewModel,而render當做View。 Model負責訪問數據庫並把數據設置到state(即View Model)上,可以用Promise和fetch API實現。 然后,render,即View,負責把View Model渲染到頁面上。

在這整套流程中,前端程序員需要編寫大量閉包組成的異步流程, 設置、訪問狀態的代碼五零四散, 一不小心就會bug叢生,就算小心翼翼的處理各種異步事件,也會導致程序變得復雜,既難調試,又難維護。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM