為什麼要使用高階元件?
想想以前用原生和jQuery的專案,上千行的code映入眼簾,瞬間有種昏死過去的衝動。程式碼難以維護,改一個bug可能出現N個bug,真的是很痛苦。於是乎元件化成為了當前前端開發的主流技術。angular、vue和react很好的幫我們實現了元件化。
但是我們常常也會遇到一種情況,就是兩個元件往往有很多的重複程式碼(可能是相同的屬性,也可能是相同的方法)。例如,在登入和註冊元件中,都會有使用者名稱和密碼,以及對他們的校驗規則。為了提高程式碼的複用性和可維護性,React高階函式應運而生。
React之前對此的解決方案是mixin,但這造成和很多不必要的問題,後來就被廢棄掉了。使用過vue的同學,不知道有沒有使用過mixin,react高階函式的作用和它是一樣的。
高階元件到底是個什麼東西?
高階元件其實是一個函式,它並不是一個元件,我們需要向它傳遞一些引數(想要操作的元件、屬性)。這麼說起來它其實一點也不高階,它的作用就是儲存一些公共的屬性和方法。
我們經常幾個人吃過一個鍋底的那種火鍋,鍋底裡有火鍋底料和各種佐料,我們把肉和蔬菜等放進去涮一下,就可以美美的飽餐一頓。高階函式在react程式設計中扮演的角色就是火鍋鍋底的角色,它有公用的方法和屬性,而各種元件就是肉和蔬菜。如果是一個人一個鍋的火鍋就像沒有經過封裝的code,程式碼量重複且維護困難。
如何實現高階函式?
我們先來看一段可以使用高階函式的程式碼:
這裡有一個Second元件,它負責展示使用者名稱username
export class Second extends React.Component {
constructor(props) {
super(props);
this.state = {
username: ''
}
}
componentWillMount() {
let username = localStorage.getItem('username');
this.setState({
username: username
});
}
render() {
return(
<div>
<legend>Second Page</legend>
<h2>Hi {this.state.username}</h2>
</div>
)
}
}複製程式碼
下面是一個Third元件,它也負責展示使用者名稱
export class Third extends React.Component {
constructor(props) {
super(props);
this.state = {
username: ''
}
}
componentWillMount() {
let username = localStorage.getItem('username');
this.setState({
username: username
});
}
render() {
return(
<div>
<legend>Third Page</legend>
<h2>Hi {this.state.username}</h2>
<p>我今年18歲了</p>
</div>
)
}
}複製程式碼
我們看到這兩個元件除了名稱以外,其餘大量的程式碼是一樣的,我們完全可以考慮將它們通用的程式碼提取出來。下面就是高階元件出場的時候了。
高階元件可以寫成這樣
export const HighOrderComponent = (WrapComponent, title) => {
return class HOC extends React.Component {
constructor(props) {
super(props);
this.state = {
username: ''
}
}
componentWillMount() {
let username = localStorage.getItem('username');
this.setState({
username: username
});
}
static displayName = `HOC(${getDisplayName(WrapComponent)})`;
render() {
return(
<div>
<legend>{title}</legend>
<WrapComponent username={this.state.username}></WrapComponent>
</div>
)
}
}
}複製程式碼
- WrapComponent 是我們要操作的元件
- title 是它們的標題引數
- username 就是我們常用的props,它負責向元件傳遞值,我們下面還會提到
使用高階元件之後我們要對Second和Third元件進行修改,修改如下
class Second extends React.Component {
render() {
return(
<div>
<h2>Hi {this.props.username}</h2>
<h3>曉不曉得哪裡好耍</h3>
</div>
)
}
}
export const HighOrderSecond = HighOrderComponent(Second, 'Second Page');複製程式碼
class Third extends React.Component {
render() {
return(
<div>
<h2>Hi {this.props.username}</h2>
</div>
)
}
}
export const HighOrderThird = HighOrderComponent(Third, 'Third Page');複製程式碼
很多同學可能會問,export出去的常量是幹什麼用的,它就是高階元件對元件進行封裝之後的一個全新的元件,是兩者的結合。到此,我們在其它頁面引用元件就不再是引用Second和Third元件了,要引用的就是HighOrderSecond和HighOrderThird了。
細心的同學可能會發現一些不同的地方,對於Second和Third的公共legend提取出去了,但並沒有將h2對應得標題提取出去,這裡只是想給大家說一下,在對元件使用高階元件包裹之後,高階元件就變成了元件的父元件,它的state可以通過props的方式向子元件傳遞,username就是這樣。我們在chrome的react外掛中可以觀察到這一點
HOC已經將Second元件包裹起來,成為了它的父元件,它上面的match和location是我使用了react-router的緣故,我們可以不用去管它。它的state——username作為props傳給了Second
今天給大家簡單的介紹了React高階元件的一些知識,後續還會再深入的挖掘React高階元件的知識和大家分享,希望對大家有幫助。