React開發者對React有兩種元件類型早已熟悉:
考慮到「類別」和「函數」的提及,自然會產生疑問:
畢竟,如果類別元件與OOP相關,那麼OOP原則(繼承、封裝、多態等)可以指導基於類別的元件的開發。類似地,FP原理可以影響函數組件。換句話說,我們可以直接將這些程式設計範式的最佳實踐應用到React專案中。
那麼,函數元件和函數式程式設計之間是什麼關係呢?本文將深入探討此主題。
首先,我們應該明確,框架語法本質上是一種DSL(領域特定語言),專為特定領域的開發而定制。
例如,React是用於建立視圖的DSL。雖然不同的平台使用不同的框架來建立視圖,例如:
這些框架通常遵循相同的DSL(React語法)。此DSL不與任何特定的程式設計範式綁定,而應被視為一套非常適合視圖開發的語言特性集合。
因此,作為React DSL的一部分:
只要這些原則有利於視圖開發,就可以將它們整合到DSL中。
例如,考慮以下由WelcomeMessage和LogoutButton組成的函數元件Header,這示範了OOP中組合優於繼承的原則:
<code class="language-javascript">function Header(props) { return ( <div> <WelcomeMessage name={props.name} /> <LogoutButton onClick={props.onLogout} /> </div> ); }</code>
同樣,考慮類別元件Cpn,其中狀態count的更新不是透過變異(this.state.count ),而是透過使用不可變資料呼叫this.setState:
<code class="language-javascript">class Cpn extends React.Component { // ... onClick() { const count = this.state.count; this.setState({ count: count + 1 }); } render() { // ... } }</code>
使用不可變資料反映了FP的原則。
因此,在探索任何React特性時,我們應該考慮以下三個步驟:
透過將此思考過程應用於函數組件和函數式程式設計之間的關係,我們發現:
這定義了它們之間的關係:函數元件是在React中實現多種程式設計範式(主要是OOP和FP)的產物,在此過程中藉鑒了FP的一些想法。
函數元件不應僅被視為React中函數式程式設計的體現。
讓我們使用前面提到的三步驟思維過程來探討函數組件的演變。 React的開發理念最好用以下公式表達:
<code class="language-javascript">function Header(props) { return ( <div> <WelcomeMessage name={props.name} /> <LogoutButton onClick={props.onLogout} /> </div> ); }</code>
為了實現這個理念,需要兩個關鍵要素:
在這裡,來自FP的不可變資料更適合作為資料快照的載體。這就是為什麼React中的狀態是不可變的——狀態的本質就是一個快照。
函數映射的載體沒有特定的要求。在React中,每次更新都會觸發重新渲染,而渲染過程本身就是函數映射過程。輸入是props和state,輸出是JSX。
相較之下,Vue組件較符合OOP原則。考慮這個Vue App元件:
<code class="language-javascript">class Cpn extends React.Component { // ... onClick() { const count = this.state.count; this.setState({ count: count + 1 }); } render() { // ... } }</code>
元件的setup方法只在初始化期間執行一次。後續更新操作在閉包內操作相同的數據,這對應於OOP中實例的概念。
由於React不會對函數映射的載體施加特殊要求,因此類別組件和函數組件都是可行的選擇。
許多人認為,透過hook改進邏輯的可重複使用性是函數元件優於類別元件的主要原因。然而,基於裝飾器的類別開發模型,尤其是在與TypeScript結合使用時,已被證明是一種有效的邏輯重用方法。
真正的原因在於函數元件能夠更好地實現UI = fn(snapshot)的理念。
如前所述,公式中的快照代表狀態的快照,在React中包含:
對於給定的元件,公式UI = fn(snapshot)確保相同的快照產生相同的輸出(JSX)。但是,狀態更新也可能觸發副作用,例如資料擷取或DOM操作。
在類別元件中,這些副作用邏輯分散在各種生命週期方法中,使得React難以控制。但在函數元件中:
<code>UI = fn(snapshot);</code>
用法:
<code class="language-javascript">const App = { setup(initialProps) { const count = reactive({ count: 0 }); const add = () => { count.value++; }; return { count, add }; }, template: "...omitted" };</code>
簡而言之,函數元件確保副作用保持可控,從而為相同的快照輸入提供一致的輸出。這與FP中純函數的概念相符,這就是為什麼函數元件已成為React中的主流選擇。
函數元件不是React中函數式程式設計的直接實現,而是實現React核心理念UI = fn(snapshot)的最合適的載體。 React整合了來自各種程式設計範式的優秀思想,其中FP的影響最大。最終,每個設計選擇都服務於整體理念。
Leapcell 是新一代無伺服器平台,用於 Web 託管、非同步任務和 Redis:
多語言支援
免費部署無限項目
無與倫比的成本效益
簡化的開發者體驗
輕鬆擴充與高效能
在文件中了解更多!
追蹤我們的 X:@LeapcellHQ
閱讀我們的部落格
以上是函數組件等於函數式程式設計嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!