天天看點

react hooks 如何自定義元件(react函數元件的封裝)

前言

  這裡寫一下如何封裝可複用元件。首先技術棧 react hooks + prop-types + jsx封裝純函數元件。類元件和typeScript在這不做讨論,大家别白跑一趟。

       接下來會說一下封裝可複用元件的思路,比如一個新手應該怎麼去封裝,都需要注意哪些東西。

  然後說一些複雜元件需要的功能,比如閉合标簽内部dom怎麼處理,其實就是插槽功能,比如資料監聽,内部做一些業務邏輯。

  想看原碼的點這裡,這是我GitHub上完整的 react hooks 項目,  點這裡,看源碼

目錄

1、思路 及 封裝的誤區

2、 props 的類型檢測、預設值

3、元件調用及資料互通

4、實作類似于vue插槽一樣的功能 (children屬性)

5、useState、useEffect等hooks講解

6、總結

一、思路

  無論是js還是C++等等,都要求 子產品内高内聚、子產品間低耦合。簡單點說就是你改了一個子產品,另一個子產品稍作修改就行,不至于改動很大。根據這個程式設計思想,一個可複用元件的對外互動,就是決定他耦合度的關鍵。把元件比作香腸機,輸入豬肉,輸出香腸。輸入就是props,輸出就是界面效果 以及 給外部回報的回調函數。關于輸入props,我們對他有要求,就是類型檢查和預設值。比如輸入的得是豬肉不能是石頭,預設做小香腸,而不是大香腸。回調函數也有要求,你得盡可能滿足可以預知的邏輯,簡單說就是你以後用這個元件的時候,需要某個資料,這個元件得支援,得有對應的回調能讓你拿到你想要的的東西。

  注意,這裡說幾個誤區,也是很多人經常犯錯的地方。

  1、項目中可複用元件我認為有2種,并不是所有元件都按照一套标準去規範

    第一種 全局可複用元件,這類元件類似于antd那種ui庫,是提供給開發項目所有人使用的,頻率高。這一類必須嚴格規範,不能亂搞。必須有props的類型檢查,有需要的props得加預設值;元件隻能接收props作為資料來源,通過回調函數回報,嚴禁其他任何形式的輸入輸出改(其實回調函數也是props,隻不過是函數類型的,為了功能上做差別,後續我都會這樣稱呼);必須對元件功能,props,内部的方法等添加注釋。

    第二種 是一些局部功能元件,這一類可能隻在部分特定情況下會使用,不需要像第一種那種嚴格要求,比較靈活多變,盡可能以簡單通俗易懂去編寫他,比如接下來要描述的幾種禁忌,這類元件并沒有這些要求,隻要代碼精簡、便于維護、易讀。你想怎麼寫都行。

  2、全局元件

    避免使用redux一類的狀态管理,能用props實作就别懶

    避免使用ref擷取元件資料,能用回調的都寫上回調,ref可讀性很差

    保持純淨,自己開發的元件可以互相引用,但是盡可能避免對第三方、包括UI架構的使用。當然這也不是絕對,二次封裝元件很常見,隻是有條件的盡量自己開發。

二、 props 的類型檢測、預設值

  我們使用prop-types做props類型檢查,得安裝一下

  看下面的代碼,首先引入 prop-types ,然後建立我們的函數元件,這裡有幾點需要注意的,首先,先定義元件,然後在元件原型上綁定類型檢查;其次因為是函數元件,所有用prop-types做類型檢查的props,都必須在函數元件的形參中顯式的聲明,否則不好使。看代碼也能了解畢竟綁定在原型上,初始化的時候不聲明,就沒辦法綁定校驗了。是以,我建議一種寫法,所有props都做檢查,都在形參中聲明,能賦預設值的,都寫上預設值,然後在形參的後面把注釋都寫明白了,這樣代碼一目了然,換個人也可以很容易接手你的代碼。這裡啰嗦一嘴,函數元件,本質就是個函數,是以預設值這些都是js函數形參賦預設值的寫法。

  額外啰嗦兩句prop-types的用法,後面這個是他的用法說明:  https://zh-hans.reactjs.org/docs/typechecking-with-proptypes.html

  連結包括所有的類型、一個props聲明多種類型,對象内部屬性的類型校驗,甚至是定義一個類型檢查函數等用法。

react hooks 如何自定義元件(react函數元件的封裝)

三、元件調用及資料互通

  處理好了props,我們處理回調,如圖所示,是我寫的一個簡單的回調。這裡一般不寫預設值,但是要做非空判斷,因為不是所有的屬性,使用者都需要。每個全局元件都需要有份文檔,不但描述邏輯功能,還有所有屬性的的描述,像函數這類,需要有示例的,形參含義說明白。

react hooks 如何自定義元件(react函數元件的封裝)

 四、實作類似于vue插槽一樣的功能 (children屬性)

  封裝元件經常會遇到需要 插槽 的情況,簡單說就是你封裝了一個閉合元件,内部的dom你想對他做一些處理,比如樣式上的。這裡說一下應該怎麼做。看圖,注意,如果有一個根标簽,children就是個對象,如果多個并列标簽的話,children就是數組,用法不一樣,這裡根據需求來,我這裡用的是對象,也就是頂層隻有一個标簽,注意需要定義children的類型,是标簽,還是一個數組的标簽。圖中代碼類型定義是一個react标簽,是以如果别人寫了并列的div,就會報警告這樣自然可以很好的限制使用者。

react hooks 如何自定義元件(react函數元件的封裝)

五、useState、useEffect等hooks講解

  最後寫一點函數元件的使用心得。首先父元件變化 或者 函數元件内部變量變化,都會導緻函數元件重新執行,如果你在return前面寫個console,會發現執行了很多次,複雜的界面甚至能執行幾十次,這點很操蛋,不過最終diff的時候react會做優化,合并很多變化,當然很多時候執行太多次,還是代碼有問題的,需要你盡可能的優化下代碼,提升性能。其次,函數元件隻有hooks,沒有生命周期,這和類元件差異很大,代碼邏輯也改變很大,很多人剛一接觸hooks和函數元件會感覺很懵逼,不知道該怎麼寫代碼。關于這點,我不打算在這裡講太多,畢竟這是介紹封裝元件的文章。react的文檔屬于心智模型,非常nice,大家應該都能看得明白,接下來我會寫幾個看文檔不容易了解,實際撸代碼又很重要的東西。

  1、函數會不斷執行,如果在函數内部聲明變量或者常量會不斷被初始化,是以要麼用useState聲明要麼直接放到函數外,比如标記1、3 、4。否則,聲明的變量就會是個定值。

  2、useState聲明的變量,預設值隻會指派一次,他隻會觸發一次,比如标記 2。

  3、函數元件沒生命周期,所有功能都集合到useEffect身上了,它 用于監聽變量變化,可以監聽useState的也可以監聽我們那個标記1這種函數外的。他第二個參數傳空數組,就隻會在元件初始化的時候執行一次,可以在這初始化資料,發http請求,或者時間綁定等。他的觸發機制實在dom渲染結束之後。比如标記 5,如果加return,解除安裝的時候也會執行return的邏輯,這其實就是他實作生命周期功能的用法之一。

  4、useMemo 通過這個hooks可以優化元件的渲染次數,它根據指定變量變化控制函數是否執行

u

react hooks 如何自定義元件(react函數元件的封裝)

六、總結

  關于react hooks封裝可複用元件,暫時就想到了這麼多,文章開頭我貼了GitHub的項目位址,因為要說的東西比較多,沒法一個例子就把所有東西清晰、條理的說明白,期間我截圖了好幾個元件的代碼,大家看源碼的話,直接看components檔案夾。

  vue3的setup參考了react hooks,從用法上說,vue的改變還能讓人接受些,畢竟他隻是将之前的屬性換到了setup的原型上。react這波真的是大變樣,類元件和函數元件真的就完全是2套代碼了。

  這裡說一下我自己的感悟,這兩個架構先是變得雍容華貴,功能很多,現在又返璞歸真,追求靈活,貼近js。對我最大的體會就是以後的碼代碼變難了。更新之後vue和react上手難度都提升了很多,提高了對js基礎的了解。有經驗的程式員寫出的代碼,精簡幹練,部分地方,新手可能會看不懂。新手寫出來的代碼,有可能亂成一鍋粥,其他人都看不懂。是以希望大家多寫注釋,好好撸代碼,把這個程式設計的風氣提高上來。

  部落客真的是遇到過很多垃圾代碼,深受其苦,大多是大家都不想優化代碼,這糊一塊,那加一段,代碼越來越亂,最後走向重構的結局。裱糊匠太難了