1. 什么是高阶组件
- 高阶组件本身是通过函数构造的
- 该函数接收一个组件作为参数
- 该函数返回一个组件
即高阶组件(Higher-Order Components,简称为 HOC):- 参数为组件,返回值为新组件的函数
https://zh-hans.reactjs.org/docs/higher-order-components.html#gatsby-focus-wrapper
import React from 'react'; class Home extends React.PureComponent{ render(){ return ( <div>Home</div> ) } } function enhanceComponent(WrappedComponent) { class AdvComponent extends React.PureComponent{ render() { return ( <div> <WrappedComponent/> </div> ) } } return AdvComponent; } const AdvComponent = enhanceComponent(Home); class App extends React.PureComponent{ constructor(props){ super(props); } render(){ return ( <div> <AdvComponent/> </div> ) } } export default App;
高阶组件的应用场景
应用场景一:减少冗余代码
如果按照上面那种思路,则下面的father的代码特别冗余
import React from 'react'; const UserContext = React.createContext({}); const {Provider, Consumer} = UserContext; class Father1 extends React.PureComponent{ render() { return ( <div> <Son1/> </div> ) } } class Father2 extends React.PureComponent{ render() { return ( <div> <Son2/> </div> ) } } class Son1 extends React.PureComponent{ render() { return ( <Consumer>{ value =>{ return ( <div> <p>{value.name}</p> <p>{value.age}</p> </div> ) } }</Consumer> ) } } class Son2 extends React.PureComponent{ render() { return ( <Consumer>{ value =>{ return ( <ul> <li>{value.name}</li> <li>{value.age}</li> </ul> ) } }</Consumer> ) } } class App extends React.PureComponent{ constructor(props){ super(props); } render(){ return ( <Provider value={{name:'zs', age:18}}> <Father1/> <Father2/> </Provider> ) } } export default App;
https://zh-hans.reactjs.org/docs/higher-order-components.html#gatsby-focus-wrapper
网络异常,图片无法展示
|
结构.png
怎么通过高阶组件进行改进呢?
因为father的代码其实非常相似,故可以考虑高阶组件通过函数构造
function EnhancedComponent (WrappedComponent) { class Father extends React.PureComponent{ render() { return ( <Consumer>{ value =>{ return ( <WrappedComponent name={value.name} age={value.age}/> ) } }</Consumer> ) } } return Father; }
import React from 'react'; const UserContext = React.createContext({}); const {Provider, Consumer} = UserContext; class Son1 extends React.PureComponent{ render() { return ( <div> <p>{this.props.name}</p> <p>{this.props.age}</p> </div> ) } } class Son2 extends React.PureComponent{ render() { return ( <ul> <li>{this.props.name}</li> <li>{this.props.age}</li> </ul> ) } } function EnhancedComponent (WrappedComponent) { class Father extends React.PureComponent{ render() { return ( <Consumer>{ value =>{ return ( <WrappedComponent name={value.name} age={value.age}/> ) } }</Consumer> ) } } return Father; } const Father1 = EnhancedComponent(Son1); const Father2 = EnhancedComponent(Son2); class App extends React.PureComponent{ constructor(props){ super(props); } render(){ return ( <Provider value={{name:'zs', age:18}}> <Father1/> <Father2/> </Provider> ) } } export default App;
上面的代码在子组件接收父组件相同的数据时其实可以简化写法为下面
<WrappedComponent {...value} /> <!-- 相当于<WrappedComponent name={value.name} age={value.age}/>-->
应用场景二:增强Props
但是通过应用一减少代码时只是解决了接收相同数据导致的代码冗余问题,但是此时又有问题是:如果两个组件传递的是不同的数据该怎么办呢?
这时需要分别通过Father组件分别传值,再通过子组件的props
接收
此时代码优化为入下:
<Provider value={{name:'zs', age:18}}> <Father1 country={'中国'}/> <Father2 country={'俄罗斯'}/> </Provider>
function EnhancedComponent (WrappedComponent) { class Father extends React.PureComponent{ render() { return ( <Consumer>{ value =>{ return ( /* <WrappedComponent name={value.name} age={value.age}/> */ <WrappedComponent {...value} {...this.props}/> ) } }</Consumer> ) } } return Father; }
完整代码:
import React from 'react'; const UserContext = React.createContext({}); const {Provider, Consumer} = UserContext; class Son1 extends React.PureComponent{ render() { return ( <div> <p>{this.props.name}</p> <p>{this.props.age}</p> <p>{this.props.country}</p> </div> ) } } class Son2 extends React.PureComponent{ render() { return ( <ul> <li>{this.props.name}</li> <li>{this.props.age}</li> <li>{this.props.country}</li> </ul> ) } } function EnhancedComponent (WrappedComponent) { class Father extends React.PureComponent{ render() { return ( <Consumer>{ value =>{ return ( <WrappedComponent {...value} {...this.props}/> ) } }</Consumer> ) } } return Father; } const Father1 = EnhancedComponent(Son1); const Father2 = EnhancedComponent(Son2); class App extends React.PureComponent{ constructor(props){ super(props); } render(){ return ( <Provider value={{name:'zs', age:18}}> <Father1 country={'中国'}/> <Father2 country={'俄罗斯'}/> </Provider> ) } } export default App;
应用场景三:抽离State+生命周期拦截
import React from 'react'; import {EventEmitter} from 'events'; const UserContext = React.createContext({}); const {Provider, Consumer} = UserContext; const eventBus = new EventEmitter(); class Son1 extends React.PureComponent{ render() { return ( <div> <p>{this.props.name}</p> <p>{this.props.age}</p> <p>{this.props.country}</p> { this.props.list.map(name=>{ return <p key={name}>{name}</p> }) } </div> ) } } class Son2 extends React.PureComponent{ render() { return ( <ul> <li>{this.props.name}</li> <li>{this.props.age}</li> <li>{this.props.country}</li> { this.props.list.map(name=>{ return <li key={name}>{name}</li> }) } </ul> ) } } function EnhancedComponent (WrappedComponent) { class Father extends React.PureComponent{ constructor(props){ super(props); this.state = { list: [] } } componentDidMount() { eventBus.addListener('update', this.update.bind(this)); } componentWillUnmount() { eventBus.removeListener('update', this.update.bind(this)); } update(list){ this.setState({ list: list }) } render() { return ( <Consumer>{ value =>{ return ( <WrappedComponent {...value} {...this.props} {...this.state}/> ) } }</Consumer> ) } } return Father; } const Father1 = EnhancedComponent(Son1); const Father2 = EnhancedComponent(Son2); class App extends React.PureComponent{ constructor(props){ super(props); } render(){ return ( <Provider value={{name:'zs', age:18}}> <Father1 country={'中国'}/> <Father2 country={'俄罗斯'}/> <button onClick={()=>{this.btnClick()}}>按钮</button> </Provider> ) } btnClick(){ eventBus.emit('update', ['鲁班', '虞姬', '黄忠']); } } export default App;
应用场景四:权限控制
一般再用户没有登陆时则显示登录界面,如果登录了的话则显示用户信息界面
import React from 'react'; class Info extends React.PureComponent{ render() { return ( <div>用户信息</div> ) } } class Login extends React.PureComponent{ render() { return ( <div>用户登录</div> ) } } function EnhancedComponent (WrappedComponent) { class Authority extends React.PureComponent{ render() { if(this.props.isLogin){ return <Info/> }else{ return <Login/> } } } return Authority; } const AuthorityInfo = EnhancedComponent(Info); class App extends React.PureComponent{ constructor(props){ super(props); } render(){ return ( <AuthorityInfo isLogin={true}/> //<AuthorityInfo isLogin={false}/> ) } } export default App;