react為何會是react - 我多希望開始學react的第一天就有人先告訴過我這些事
首先先來看看 react 在它 github repo 的敘述
A declarative, efficient, and flexible JavaScript library for building user interfaces. from
declarative
指的是我們UI-programing時可以用宣告式
的 programing style 來寫,我們在每個 component 裡在寫的,都是:如果某個值是 oo 那我的 UI 要長這樣(就是那一堆 JSX),如果某個值是 xx 那我的 UI 要長那樣... 而不是像以前 vanilla JS 或是 jQuery 時代那樣,自己去createElement, appendChild.....這樣叫做 imperative -命令式
,傳統型的作法:先做這個,然後再做那個...一步一步地下指令。 declarative 式的狀況下,我們在 UI-programing 時會變成專注在當props是怎樣的時候我的UI要長什麼樣
。我們就是出一張嘴
,寫好 component 在各種狀況時要 return 的UI描述
(就是 class component 時代裡 render 和 function component 在return
的那些 JSX)。在絕大部分狀況我們不用自己去 操作 dom(指的就是 getElementById, createElement, appendChild...那些動作),react 會幫我們做, 然後我們期待 UI 框架幫我們讓瀏覽器去做到最少的 reflow 跟 repaint。react 是如何讓它的 user 能夠改採用 declarative 式的 programing?
瀏覽器提供讓我們去改變畫面手段的其實就是 createElement, removeChild, appendChild, createDocumentFragment...這些 web api,到最後 react 還是用它們在幫我們更新畫面。我們寫的 component 在每次新的 props 被傳進來(其實就是 function 接到新的參數再次被執行), state 被改變時,就會從新執行,return 新的UI描述
,react 內部會保留著上次的UI描述
,跟這次新產生出來的做比對
(diff, reconcile)就能夠知道再來應該要更新畫面上的哪裡, 這些上一次跟這一次的 UI 描述其實就是所謂的VDom
,所以 VDom 根本就跟瀏覽器的 dom 完全沒有關係,VDom 純粹就是 react 為了要知道每次重新運算
過後,要去更新哪裡,所需要的資料
。
所以這些不斷被執行的 component(其實它們就是 function) return 出來的UI描述
跟比對的動作就是 react 能讓我們用 declarative 式開發的原因。
被誤解的 render
render: 但是我比較喜歡 `算繪` 這個翻譯。詳見reference裡的 `論 Render 翻譯(算繪/演繹)` 一文今天中文翻譯幾乎都翻成 渲染
*,指的是畫出畫面,class component 時代的其中一個 life cycle 就叫 render,但是這個 render 根本就不是在畫出畫面
,經過我們上面的思考之後,我們已經充分知道,它就是最後 return 出UI描述
的那個動作而已。
更新畫面,畫出畫面,這是只有瀏覽器才做得到的事情。所以一定要記住,react 裡的 render 不是畫,只是在 return 出UI描述
,使它們成為所謂的 VDom 裡的一部分,認真要給個適當的名詞的話,其實比較接近計算
(calculate)。
這是各大神都承認過的事情,當初會叫render
只是當初 react 在 2013 剛出來的時候把virtual-dom
拿來當行銷名詞,為了配合virtual-dom
這個詞所以才會使用render
這個詞:
Ryan Florence (react-router的作者之一):
Dan Abramov:Wondering if in React instead of saying "next render" we should start saying "next call".
— Ryan Florence (@ryanflorence) October 28, 2019
A component/hook being called is not a 1:1 relationship with actual rendering.
Then we could give render its actual meaning again.
I dunno. Just thinking out loud to thousands of people.
I mean that “rendering” in React is essentially calculating. The only reason it’s called rendering is to feel more familiar to people in 2013.
— Dan Abramov (@dan_abramov) November 29, 2019
cpu 花在 reflow 和 repaint 的時間降低了,但是 scripting 的比例昇高了
前面也說到 react 會不斷比對前一次跟這一次的 VDom 來決定要 update 畫面上的哪裡,所以 component 不斷地被執行,diff 的動作也不斷地在做,所以 cpu 不斷地在執行很多的 js,不過這也是在為了確保畫面跟 state 之間的同步, 記憶體裡儲存了前一次的 VDom 跟這一次的 VDom 也會讓使用react寫出來的web app使用的記憶體相較於直接操作dom的時候用得比較多。
diff與VDom是react為了達到declarative UI programing所使用的手段,但也是成本
不斷地執行component然後diff,是為了確保UI會即時地反映state,儘管diff演算法一直不斷地在被優化,但是我們在使用react做Web UI programing時還是必須要對它背後的運作原理有個正確的mental model,才能在bug發生或是效能需要優化時做出比較正確的思考。