1. 前言
1.高階組件是
react
組件總結(jié)中最難的一種,平匙昵鳎基本用不到,就算能用到也給規(guī)避了,所以也導致很多人不會
2.這幾天結(jié)合之前的一些粗淺經(jīng)驗,搞了個簡單的梳理,最終梳理出幾個相對簡單易懂的課件,不足之處,歡迎交流
2. 是什么 what
高階組件(Higher Order Component,簡稱:HOC ):
1.是 React 中用于
重用組件邏輯
的高級技巧.
2.HOC 自身不是
ReactAPI
的一部分,它是一種基于 React 的組合特性
而形成的設計模式
3.高階組件
是參數(shù)
為組件裳食,返回值為新組件的函數(shù)
玫恳。
簡單理解
一個高階組件只是一個包裝了另外一個 React 組件的 組件辨赐。
這種形式通常實現(xiàn)為一個函數(shù),本質(zhì)上是一個類工廠(class factory
3.優(yōu)點
1.實現(xiàn)了對原有組件的
增強和優(yōu)化
,
2.可以對原有組件
中的state, props和邏輯執(zhí)行增刪改操作, 一般用于代碼重用
和組件增強優(yōu)化
4. 應用場景
- 需要代碼重用時, react如果有多個組件都用到了
同一段邏輯
, 這時,就可以把共同的邏輯部分提取出來,利用高階組件的形式將這段邏輯整合到每一個組件中, 從而減少代碼的邏輯重復
- 需要組件
增強優(yōu)化時
, 比如我們在項目中使用的組件有些不是自己寫的, 而是從網(wǎng)上擼下來的,但是第三方
寫的組件可能比較復雜, 有時不能完全滿足需求, 但第三方組件不易修改, 此時也可以用高階組件,在不修改原始組件的前提下, 對組件添加滿足實際開發(fā)需求的功能
3.其實主要就是針對優(yōu)點 的應用
4.也可以用來替換mixins
混入
4. 組件和 高階組件的區(qū)別
1.組件是將 props 轉(zhuǎn)換為 UI
2.高階組件是將組件轉(zhuǎn)換為另一個組件
5. 實現(xiàn)方式
5.1 屬性代理
(Props Proxy): 通過創(chuàng)建新組件來包裹原始組件, 把原始組件作為新組件的子組件渲染
功能: 可實現(xiàn)對原始組件的 props數(shù)據(jù)更新 和 組件模板更新
5.2 反向繼承
(Inheritance Inversion): 通過創(chuàng)建新組件繼承自原始組件, 把原始組件作為父組件
功能: 可實現(xiàn)對原始組件的state狀態(tài)數(shù)據(jù)更新 和 組件模板更新
好了已經(jīng)一大堆理論了,上代碼 再接著理論
6. 鋪墊 引出工作/代碼
6.1 代碼
localStorage.setItem("userInfo", JSON.stringify({ name: "yzs", description: "生活如此多嬌" }))
class UserView extends React.Component {
constructor(props) {
super(props)
this.state = { userInfo: {} }
}
componentDidMount() {
let userInfo = JSON.parse(localStorage.getItem("userInfo"))
this.setState({ userInfo })
}
render() {
let { userInfo } = this.state
return (
<div>
<h1>{userInfo.name}</h1>
<p>{userInfo.description}</p>
</div>
)
}
}
6.2 分析
1.上述 獲取
userInfo
的邏輯要在好多地方使用,
2.那么在使用的地方都需要重寫 constructor componentDidMount ,顯然這是冗余操作
3.這個時候需要代碼 重用,所以可以選擇高階組件,對應上述的優(yōu)點之一
7. 屬性代理 用法
高階函數(shù)的基本結(jié)構(gòu)是 函數(shù),參數(shù)是組件,返回新的組件
所以基本寫法都是差不多的
7.1 基本結(jié)構(gòu)
function withUserData(WrappedComponent) {
return class extends React.Component {
constructor(props) {
super(props)
this.state = { userInfo: {} }
}
componentDidMount() {
let userInfo = JSON.parse(localStorage.getItem("userInfo"))
this.setState({ userInfo })
}
render() {
// ...this.props 傳遞給當前組件的屬性繼續(xù)向下傳遞
return <WrappedComponent userInfo={this.state.userInfo} {...this.props} />
}
}
}
7.2 分析
1.函數(shù)名字可以隨便起
2.參數(shù)名一般都是WrappedComponent
, ed代表被包裹 ,所以整體代表 被包裹的組件,
注意
3.這里只封裝了獲取
userInfo
數(shù)據(jù)的邏輯,render
,布局可以不管
4.然后以屬性的形式傳遞給包裝的組件WrappedComponent
5.WrappedComponent
中直接通過props
屬性獲取需要的數(shù)據(jù)
6.其他組件也需要這段邏輯時就可以通過withUserData
高階組件包裝組件來使用
拔高
1.高階組件的主要功能是封裝并分離組件的通用邏輯京办,讓通用邏輯在組件間更好地被復用掀序。
2.高階組件的這種實現(xiàn)方式,本質(zhì)上是一個裝飾者設計模式惭婿。
8. 使用高階組件
8.1 需要使用的組件
class UserView2 extends React.Component {
render() {
// 注意這里變?yōu)?props屬性接收傳值
let { userInfo } = this.props
return (
<div>
<h1>{userInfo.name}</h1>
<p>{userInfo.description}</p>
</div>
)
}
// 省略其他邏輯,重點是當前知識點
}
這個組件也需要用到獲取
userInfo
數(shù)據(jù)的邏輯
8.2 和高階組件聯(lián)合使用
const UserHOC = withUserData(UserView2)
函數(shù)調(diào)用,參數(shù)是組件
8.3 顯示
let App = () => {
return (
<div>
<h1>App</h1>
<UserView />
<UserHOC />
</div>
)
}
ReactDOM.render(<App />, document.querySelector("#app"))
直接作為組件來使用
9. 高階組件與父組件區(qū)別
這里很多道友有疑問了,這不和父組件一樣嘛干啥這么麻煩呢
1.首先從邏輯的執(zhí)行流程上來看不恭,高階組件確實和父組件比較相像,
2.但是高階
組件強調(diào)的是邏輯
的抽象财饥。高階組件是一個函數(shù)
换吧,函數(shù)關(guān)注的是邏輯;
3.父組件
是一個組件钥星,組件主要關(guān)注的是UI/DOM
沾瓦。如果邏輯是與DOM直接相關(guān)的,那么這部分邏輯適合放到父組件中實現(xiàn)谦炒;
4.如果邏輯是與DOM不直接相關(guān)的贯莺,那么這部分邏輯適合使用高階組件抽象,如數(shù)據(jù)校驗编饺、請求發(fā)送等乖篷。
10.后續(xù)
看來一篇文章還真不行,接著寫