什么是高階組件?
高階部件是一種用於復用組件邏輯的高級技術,它並不是 React API的一部分,而是從React 演化而來的一種模式。 具體地說,高階組件就是一個接收一個組件並返回另外一個新組件的函數!
解決什么問題?
隨着項目越來越復雜,開發過程中,多個組件需要某個功能,而且這個功能和頁面並沒有關系,所以也不能簡單的抽取成一個新的組件,但是如果讓同樣的邏輯在各個組件里各自實現,無疑會導致重復的代碼。比如頁面有三種彈窗一個有title,一個沒有,一個又有右上角關閉按鈕,除此之外別無它樣,你總不能整好幾個彈窗組件吧,這里除了tilte,關閉按鈕其他的就可以做為上面說的基本材料。
高階組件總共分為兩大類
-
代理方式
-
操縱prop
-
訪問ref(不推薦)
-
抽取狀態
-
包裝組件
-
繼承方式
-
操縱生命周期
-
操縱prop
代理方式之 操縱prop
import React from 'react' function HocRemoveProp (WrappedComponent) { return class WrappingComPonent extends React.Component{ render() { const { user, ...otherProps } = this.props; return <WrappedComponent {...otherProps} /> } } } export default HocRemoveProp;
增加prop
接下來我把簡化了寫法,把匿名函數去掉,同時換成箭頭函數
import React from 'react' const HocAddProp = (WrappedComponent,uid) => class extends React.Component { render() { const newProps = { uid, }; return <WrappedComponent {...this.props} {...newProps} /> } } export default HocAddProp;
兩個高階組件的使用方法:
-
const newComponent = HocRemoveProp(SampleComponent);
-
const newComponent = HocAddProp(SampleComponent,'1111111');
也可以利用decorator語法糖這樣使用
import React, { Component } from 'React'; @HocRemoveProp class SampleComponent extends Component { render() {} } export default SampleComponent;
代理方式之 抽取狀態
將所有的狀態的管理交給外面的容器組件,這個模式就是 抽取狀態 外面的容器就是這個高階組件
const HocContainer = (WrappedComponent) => class extends React.Component{ constructor(props) { super(props) this.state = { name: '' } } onNameChange = (event) => { this.setState({ name: event.target.value }) } render() { const newProps = { name: { value: this.state.name, onChange: this.onNameChange } } return <WrappedComponent {...this.props} {...newProps} /> } }
@HocContainer class SampleComponent extends React.Component { render() { return <input name="name" {...this.props.name}/> } }
這樣當我們在使用這個已經被包裹的input組件(SampleComponent)時候 它的值就被放在了HocContainer高階組件中,當很多這樣的input組件都用這個HocContainer高階組件時,那么它們的值都將保存在這個HocContainer高階組件中
代理方式之 包裝組件
const HocStyleComponent = (WrappedComponent, style) => class extends React.Component{ render() { return ( <div style={style}> <WrappedComponent {...this.props} {...newProps} /> </div> ) } }
import HocStyleComponent from './HocStyleComponent'; const colorSytle ={color:'#ff5555'} const newComponent = HocStyleComponent(SampleComponent, colorSytle);
-
代理方式下WrappedComponent會經歷一個完整的生命周期,產生的新組件和參數組件是兩個不同的組件,一次渲染,兩個組件都會經歷各自的生命周期
-
而在繼承方式下,產生的新組件和參數組件合二為一,super.render只是生命周期中的函數,變成一個生命周期。
繼承方式之 操縱prop
const HOCPropsComponent = (WrappedComponent) => class extends WrappedComponent{ render() { const elementsTree = super.render(); let newProps = { color: (elementsTree && elementsTree.type === 'div') ? '#fff': '#ff5555' }; const props = Object.assign({}, elementsTree.props, newProps) const newElementsTree = React.cloneElement(elementsTree,props,elementsTree.props.children) return newElementsTree } }
這樣就傳入了新的props
React.cloneElement( element, [props], [...children])
克隆並返回一個新的 ReactElement ,新返回的元素會保留有舊元素的 props、ref、key,也會集成新的 props。