什么是高階組件?
高階組件就是接受一個組件作為參數並返回一個新組件的函數。這里需要注意高階組件是一個函數,並不是組件,這一點一定要注意。同時這里強調一點高階組件本身並不是 React API。它只是一種模式,這種模式是由React自身的組合性質必然產生的。更加通俗的講,高階組件通過包裹(wrapped)被傳入的React組件,經過一系列處理,最終返回一個相對增強(enhanced)的 React 組件,供其他組件調用。
react中獲取的ref是什么?
- 如果ref寫在組件上,那么獲取的是 組件的實例對象;
- 如果ref寫在組件內的標簽上(div,span等),獲取的相應的DOM節點那么可知本文中獲取的高階組件的ref所指的是組件的實例對象即 子組件的this
獲取方式:
@withRouter
export default class childComponent extends Component {
constructor(props) {
super(props);
this.state = {};
const { getInstance } = props;
if (typeof getInstance === 'function') {
getInstance(this); // 在這里把this暴露給`parentComponent`
}
}
render() {
return (<div>this is childComponent</div>)
}
}
@withRouter
export default class parentComponent extends Component {
constructor(props) {
super(props);
this.state = {};
}
render () {
return (
<childComponent
ref={(withRouter) => { this.childCpWrapper = withRouter; }} // 這里獲取的是`withRouter`組件,一般沒啥用,這里寫出來只是為了對比
getInstance={(childCp) => { this.childCp = childCp; }} // 這里通過`getInstance`傳一個回調函數接收`childComponent`實例即可
/>
);
}
}
下面將上面的方法優化一下,單獨寫一個類來獲取
// 只做一件事,把`WrappedComponent`回傳個`getInstance`(如果有的話)
export default (WrappedComponent) => {
return class withRef extends Component {
static displayName = `withRef(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`;
render() {
// 這里重新定義一個props的原因是:
// 你直接去修改this.props.ref在react開發模式下會報錯,不允許你去修改
const props = {
...this.props,
};
const { getInstance } = props;
if (typeof getInstance === 'function') {
// 在這里把getInstance賦值給ref,
// 傳給`WrappedComponent`,這樣就getInstance能獲取到`WrappedComponent`實例
props.ref = getInstance;
}
return (
<WrappedComponent {...props} />
);
}
};
};
// 如何使用?
@withRouter
@withRef // 這樣使用是不是方便多了,注意:這句必須寫在最接近`childComponent`的地方
export default class childComponent extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (<div>this is childComponent</div>)
}
}
@withRouter
export default class parentComponent extends Component {
constructor(props) {
super(props);
this.state = {};
}
render () {
return (
<childComponent
// 這里獲取的是`withRouter`組件,一般沒啥用,這里寫出來只是為了對比
ref={(withRouter) => { this.childCpWrapper = withRouter; }}
// 這里通過`getInstance`傳一個回調函數接收`childComponent`實例即可
getInstance={(childCp) => { this.childCp = childCp; }}
/>
);
}
}