天天看點

将函數作為子元件的元件

<b>本文講的是将函數作為子元件的元件,</b>

<b></b>

我最近在 Twitter 上發起了關于高階元件和将函數作為子類的元件的投票,得到的結果讓我很意外。

如果你不知什麼是“函數作為子元件的元件”,我試圖通過這篇文章告訴你:

函數作為子元件的元件是什麼。

它為什麼有用。

我隻想享受分享的快樂,而不是收獲一些 Twitter 轉發,點贊,或是上一些 newsletter 等等。你懂我的意思吧?

“函數作為子元件的元件”是接收一個函數當作子元件的元件。這種模式的實施和執行得益于 React 的 property types。

沒錯!通過函數作為子類元件的元件我們就能解耦父類元件和它們的子類元件,讓設計者決定選用哪些參數及怎麼将參數應用于子類元件。例如:

其他使用這一元件的人可能考慮以不同的方式使用 name ,比如使之作為一個元素的屬性:

這裡真正奇妙的地方在于,MyComponent ,可以讓函數作為子類元件的元件管理狀态而不用關心它們是如何使用這些狀态的。讓我們再來一個更真實的例子。

Ratio 元件将使用裝置的寬度,監聽 resize 事件并将寬度、高度以及一些描述是否完成尺寸計算的資訊傳給它的子元件。

首先我們從函數作為子類元件的元件的代碼片段開始,這片段在所有子元件函數中都是常見的,它隻是讓 Comsumer 知道我們期望一個函數作為子元件,而不是 React 節點。

接下來讓我們設計 API ,我們想要一個 X Y 軸的比率,然後我們使用目前的寬度來計算,可以設定一些内部 state 來管理寬度和高度,無論我們是否已經計算了。此外,也該讓 propTypes 和 defaultProps 在使用元件時發揮點作用。

實際上我們還沒有做什麼有趣的事情,讓我們來添加一些事件監聽,并計算實際寬度(根據我們比率的變化):

好吧,在這我做了很多東西。我們添加了一些事件監聽來監聽 resize 事件以及使用提供的比率計算實際的寬度高度。是以我們得到的寬高在元件的 state 裡,那我們如何與其他元件共享它們呢?

這是一件難以了解的事情,因為它很容易讓人認為“這就完了?”,但事實這就是全部了。

這意味着想要計算出寬度和高度,我們隻需要提供參數:

現在任何人都可以使用比例元件通過提供的寬度以他們喜歡的方式來正确計算出高度!例如,有人可以使用比例元件來設定 img 上的比例:

同時,在另一個檔案中,有人決定使用它來設定 CSS 屬性。

在另一個 app 裡,有人正根據計算高度使用不同的子類元件:

構造元件的開發人員能自主要制如何傳遞和使用這些屬性。

函數作為子類元件的元件的作者不強制元件的值如何被利用,允許它非常靈活的使用。

Comsumers 不需要建立另一個元件來決定怎樣從“高階元件”傳入屬性。高階元件通常在組成的元件上強制執行屬性名稱。 為了解決這個問題,許多“高階元件”提供了一個選擇器函數,允許 Comsumers 選擇你的屬性名稱(請參考 redux 連接配接選擇功能)。這不是函數子元件的問題。

不污染 “props” 命名空間,這允許你同時使用 “Ratio” 元件和 “Pinch to Zoom” 元件,不管它們是否都會計算寬度。高階元件帶有與它們組成的元件相關的隐式契約,不幸的是這可能意味着 prop 的名稱會發生沖突以至于高階元件無法與其他元件進行組合。

高階元件在你的開發工具群組件本身中建立一個間接層,例如設定在元件上的常量被高階元件封裝後将無法使用。例如:

然後被高階元件封裝,

和你的常量說再見吧。因為如果沒有高階元件提供的函數,你将再也不能通路到這個常量。哭。

大多數時候我們會認為“我需要一個高階元件來實作這個共享功能!”根據我的經驗,我相信在多數情況下函數作為子類元件的元件是一個更好的替代方法來抽象你的 UI 問題,除非你的子元件與其組合的高階元件真正耦合。

補充一下,我認為高階元件的名稱不正确,盡管現在嘗試修改已經有點晚了。高階函數是至少執行一下操作之一的函數:

将n個函數作為參數。

傳回一個函數作為結果。

事實上,高階元件做了類似的事情,也就是拿一個元件作為參數并傳回一個元件,但是我更容易将高階元件看作是工廠函數,它是一個能動态建立的元件将允許的功能用于元件的運作組合。然而,在運作組合的時候他們是不知道你的 React 的 state 和 props 。

函數作為子類元件的元件允許你的元件們在作出組合決策時可以通路 state , props 和上下文。當函數作為子元件:

将一個函數作為參數。

渲染此函數的結果。

我覺得它們應該被命名為“高階元件”,因為它像高階函數隻使用元件組合技術而不是功能組合。好吧,現在我們還是繼續用“将函數作為子類的元件”這個粗暴的名字。

<a href="https://gist.github.com/iammerrick/c4bbac856222d65d3a11dad1c42bdcca">Pinch to Zoom - Function as Child Component</a>

<b>原文釋出時間為:2017年5月10日</b>

<b>本文來自雲栖社群合作夥伴掘金,了解相關資訊可以關注掘金網站。</b>