React.js |高阶组件的应用
什么是高阶组件
高阶组件(HOC)是 React 中用于复用组件逻辑的一种技巧,让它重复的逻辑在许多组件中得到共享。简单的说,高阶组件是一个以组件作为参数,并返回新组件的函数。
//其中WrapedComponent是包裹后的组件,wrapedComponent是高阶组件(函数),RawComponent是你想包裹的组件
const WrapedComponent = wrapedComponent(RawComponent);
应用场景1-更改props
//WrapComponent.js(高阶组件)
const wrapComponent = (OriginalComponent) => class extends Component{
handleClick(){console.log('Well Done!')}
render(){
const newProps={
say:'Click me!',
handleClick:this.handleClick
}
//先是解构原来的,后面解构新加入的
return(
<OriginalComponent {...this.props} {...newProps}/>
)
}
}
//SayHi.js(原始组件)
//1.引入高阶组件
import wrapComponent from './WrapComponent'
//2.原始组件
function SayHi(props){
return(
<div>hello!{props.name}<br/><h1 onClick={props.handleClick}>{props.say}</h1></div>
)
}
//3.导出包裹后的组件
export default wrapComponent(SayHi)
//App.js
import SayHi from './SayHi'
class App extends Component {
render(){
return(
<SayHi name={'Lisa'}/>
)
}
}
应用场景2-与其他组件一起包裹
//传进来的组件在另一个组件OtherComponent中渲染,最后返回另一个组件OtherComponent
//这意味着可以将一些常用的生命周期放在这里,那么在原来的组件就不必重复写
function wrapComponent(OriginalComponent) {
class OtherComponent extends React.Component {
componentDidMount(){
console.log('常用的')
}
render() {
return <OriginalComponent {...this.props}/>;
}
}
return OtherComponent
}
应用场景3-抽离state
一般写法:
class Form extends React.Component{
state = {user:"",psw:""}
onUserChange = (e)=>{
this.setState({user: e.target.value})
}
onPswChange = (e)=>{
this.setState({psw: e.target.value})
}
render(){
return(
<div>
<div>
用户名:<input type="text" value={this.state.user} onChange={this.onUserChange}/>
</div>
<br/>
<div>
密码:<input type="text" value={this.state.psw} onChange={this.onPswChange}/>
</div>
<div>
<p>变动:</p>
<p>{this.state.user}|{this.state.psw}</p>
</div>
</div>
)
}
}
抽离state后的写法:
const wrapComponent = (OriginalComponent) => class extends Component{
constructor(props) {
super(props)
this.state = {user:"",psw:""}
this.onUserChange = (e)=>{
this.setState({user: e.target.value})
}
this.onPswChange = (e)=>{
this.setState({psw: e.target.value})
}
}
render(){
const newProps={
user:{
value:this.state.user,
onChange: this.onUserChange,
},
psw:{
value:this.state.psw,
onChange: this.onPswChange
}
}
return(
<OriginalComponent {...this.props} {...newProps}/>
)
}
}
//Form.js
import wrapComponent from './WrapComponent'
function Form(props){
return(
<div>
<div>
用户名:<input type="text" {...props.user}/>
</div>
<br/>
<div>
密码:<input type="text" {...props.psw}/>
</div>
<div>
<p>变动:</p>
<p>{props.user.value}|{props.psw.value}</p>
</div>
</div>
)
}
export default wrapComponent(Form)
应用场景4-反向继承
//WrapComponent.js
function wrapComponent(OriginalComponent){
return class WrapComponent extends OriginalComponent{
componentDidMount(){
console.log(this.state)
this.setState({
count:1
})
setInterval(()=>{
this.setState({count:this.state.count+1})
}, 1000)
//2.也可以继承其他。例如state,props,组件生命周期,以及渲染方法
//下面是继承了一个生命周期
super.componentDidMount()
}
render(){
//1.继承render
return super.render()
}
}
}
export default wrapComponent
//Counter.js
import wrapComponent from './WrapComponent'
class Counter extends React.Component {
constructor(){
super();
this.state = {count : '无'}
}
componentDidMount(){
console.log('有事吗?')
}
render(){
return (
<div>
{this.state.count}
</div>
)
}
}
export default wrapComponent(Counter)
默认只打印高阶组件里面的,只有当super了才会打印继承过来的。
应用场景5-利用反向继承劫持渲染
把高阶组件的render变换一下,现在只要当传过来的start为true时才会渲染
//WrapComponent.js
render(){
if (this.props.start) {
return super.render()
} else {
return null
}
//return super.render()
}
//App.js
import Counter from './Counter'
class App extends Component {
render(){
return(
<Counter start={true}/>
)
}
}
多个参数
-
有时候高阶组件只接收一个参数
const AfterWrap = wrapComponent(SayHi);
-
也可以接收多个参数,比如接收配置对象用于指定组件的数据依赖:
//假设 "DataSource" 是个全局范围内的数据源变量 const BlogPostWithSubscription = withSubscription( BlogPost, (DataSource, props) => DataSource.getBlogPost(props.id) );
//传进来的第二个参数实际上是能获取并返回数据的函数 function withSubscription(WrappedComponent, selectData) { return class extends React.Component { constructor(props) { super(props); this.state = { data: selectData(DataSource, props) }; } //... handleChange() { this.setState({ data: selectData(DataSource, this.props) }); } render() { return <WrappedComponent data={this.state.data} {...this.props} />; } }; }
该示例具体的看这里https://react.docschina.org/docs/higher-order-components.html
参考