您好,登錄后才能下訂單哦!
一、高階組件
1. 高階組件(Higher Order Component,HOC)并不是React提供的某種API,而是使用React的一種模式,用于增強現(xiàn)有組件的功能。一個高階組件就是一個函數(shù),這個函數(shù)接受一個組件作為輸入,然后返回一個新的組件作為結果,而且,返回的新組件擁有了輸入組件所不具備的功能。這里提到的組件并不是組件實例,而是組件類,也可以是一個無狀態(tài)組件的函數(shù)。
高階組件的意義:
(1)重用代碼。有時候很多React組件都需要公用同樣一個邏輯,比如說React-Redux中容器組件的部分,沒有必要讓每個組件都實現(xiàn)一遍shouldComponentUpdate這些生命周期函數(shù),把這部分邏輯提取出來,利用高階組件的方式應用出去,就可以減少很多組件的重復代碼。
(2)修改現(xiàn)有React組件的行為。有些現(xiàn)成的React組件并不是開發(fā)者自己開發(fā)的,來自于第三方,或者即便是我們自己開發(fā)的,但是我們不想去觸碰這些組件的內部邏輯,這時候可以用高階組件。通過一個獨立于原有組件的函數(shù),可以產生新的組件,對原有組件沒有任何侵害。
二、代理方式的高階組件
高階組件的特點是返回的新組建類直接繼承自React.Component類,新組件扮演的角色是傳入參數(shù)組件的一個“代理”,在新組件的render函數(shù)中,把被包裹組件渲染出來,除了高階組件自己要做的工作,其余功能全部轉手給了被包裹的組件。如果高階組件要做的功能不涉及除了render之外的生命周期函數(shù),也不需要維護自己的狀態(tài),那也可以干脆返回一個純函數(shù),像上面的removeUserProp,代碼如下:
代理方式的高階組件,可以應用在下列場景中:
操縱prop
代理類型高階組件返回的新組件,渲染過程也被新組件的render函數(shù)控制,而render函數(shù)相當于一個代理,完全決定如何使用被包裹的組件。在render函數(shù)中,this.props包含新組件接收到的所有prop,最簡單的方式是把this.props原封不動的傳遞給被包裹的組件,當然,高階組件也可以增減,刪除,修改傳遞給包裹組件的props列表。
下面是一個增加props的例子:
這個高階組件addNewProps增加了傳遞給包裹組件的prop,而不是刪除prop,我們讓addNewProps不只接受被包裹參數(shù),還增加了一個new-Props參數(shù),這樣高階組件的復用性更強,利用這樣的高階組件可以給不同的組件擴充新的屬性,代碼如下:
上面的代碼中,新創(chuàng)造的FooComponent被添加了名為foo的prop,BarComponent被添加了名為bar的prop,除此之外,兩者的功能也不一樣,因為一個是通過Demo-Component產生,另一個是通過OtherComponent產生。由此可見,一個高階組件可以重用在不同的組件上,減少代碼的重復。
訪問ref
訪問ref并不是React組件推薦的使用方式,此處不做詳細的介紹。
抽取狀態(tài)
其實我們已經使用過”抽取狀態(tài)“的高階組件了,react-redux中的connect函數(shù)本身不是高階組件,但是connect函數(shù)執(zhí)行的結果是另一個函數(shù),這個函數(shù)是高階組件。
在傻瓜組件和容器組件的關系中,通常讓傻瓜組件不要管理自己的狀態(tài),只要做一個無狀態(tài)的組件就好,所有狀態(tài)的管理都交給外面的容器組件,這個模式就是”抽取狀態(tài)“。
三、繼承方式的高階組件
繼承方式的高階組件采用繼承關系關聯(lián)作為參數(shù)的組件和返回的組件,假如傳入的組件參數(shù)是WrappedComponent,那么返回的組件就直接繼承自WrappedComponent。
我們用繼承方式重新實現(xiàn)一遍removeUserprop這個組件,代碼如下:
代理方式和繼承方式最大的區(qū)別,是使用被包裹組件的方式。
在代理方式下,render函數(shù)中的使用被包裹組件是通過JSX代碼:
return <WrappedComponent {...otherProps}>
在繼承方式下,render函數(shù)中渲染被包裹組件的代碼如下:
return super.render()
因為我們創(chuàng)造的新組件繼承自傳入的WrappedComponent,所以直接調用super.render就能夠得到渲染出來的元素。
注意:在代理方式下,WrappedComponent經歷了一個完整的生命周期,但在繼承方式下super.render只是一個生命周期中的一個函數(shù)而已,在代理方式下產生的新組件和參數(shù)組件是兩個不同的組件,一次渲染,兩個組件都要經歷各自的生命周期,在繼承方式下兩者合二為一,只有一個生命周期。
上面的例子直接修改了this.props,這種做法是不推薦的!
繼承方式的高階組件可以應用于下列場景:
四、以函數(shù)為子組件
高階組件的缺點:對原有組件的props有了固化的要求。也就是說,能不能把一個高階組件作用于一個組件X,要先看一下這個組件X是不是能夠接受高階組件傳過來的props,如果組件X并不支持這些props,或者對這些props命名有不同,或者使用方式不是預期的方式,那也就沒有辦法應用這個高階組件。
“以函數(shù)為子組件”的模式就是為了克服高階組件的這種局限而生的。在這種模式下,實現(xiàn)代碼重用的不是一個函數(shù),而是一個真正的React組件,這樣的React組件有個特點,要求必須有子組件的存在,而且這個子組件必須是一個函數(shù)。在組件實例的生命周期函數(shù)中,this.props.children引用的就是子組件,render函數(shù)會直接把this.props.children當做函數(shù)來調用,得到的結果就可以作為render返回結果的一部分。
代碼如下:
AddUserProp首字母大寫,因為現(xiàn)在創(chuàng)造的是一個真正的組件類,而不是一個函數(shù),這個類的代碼,和被增強組件的唯一聯(lián)系就是this.props.children,而且this.props.children是函數(shù)類型,在render函數(shù)中直接調用this.props.children,參數(shù)就是我們希望傳遞下去的user。
使用這個AddUserProp的靈活之處在于它沒有對被增強組件有任何props要求,只是傳遞一個參數(shù)過去,至于怎么使用,完全由作為子組件的函數(shù)決定。
對于AddUserProp的使用,如下:
作為AddUserProp子組件的函數(shù),成為了連接父組件和底層組件的橋梁。一個函數(shù)可以包含各種邏輯,這樣就給使用AddUserProp提供了最大的靈活性?!耙院瘮?shù)為子組件”的模式沒有高階組件那么多分類和應用場景,因為以函數(shù)為連接橋梁的方式已經提供了無數(shù)中用例。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。