⾼阶组件—HOC(Higher-Order Components)
- ⾼阶组件是为了提⾼组件的复⽤率⽽出现的,抽离出具有相同逻辑 或相同展示的组件
- ⾼阶组件其实是⼀个函数,接收⼀个组件,然后返回⼀个新的组件,返回的这个新的组件可以对属性进⾏包装,也可以重写部分⽣命周期
- 例:
// 高阶组件,接收⼀个组件,返回⼀个新的组件 const withHOC = (Comp) => { const newComponent = (props) => { return <Comp {...props} name='Steven Wong' />; }; return newComponent; }; class HOC extends Component { render() { return ( <div> <h1>{this.props.title}</h1> <p>{this.props.name}</p> </div> ); } } export default withHOC(HOC);
⾼阶组件的链式调⽤
- 编写⼀个⾼阶组件进⾏属性的添加
- 编写⼀个⾼阶组件编写⽣命周期
- 然后将以上两个⾼阶组件进⾏链式调⽤
- 例:
// 高阶组件,接收⼀个组件,返回⼀个新的组件 const withHOC = (Comp) => { const newComponent = (props) => { return <Comp {...props} name='Steven Wong' />; }; return newComponent; }; // 高阶组件,重写生命周期,需要class组件返回class组件 const withLifeCycle = (Comp) => { class newComponent extends Component { componentDidMount() { console.log('重写componentDidMount生命周期'); } render() { return <Comp {...this.props} />; } } return newComponent; }; class HOC extends Component { render() { return ( <div> <h1>{this.props.title}</h1> <p>{this.props.name}</p> </div> ); } } export default withLifeCycle(withHOC(HOC));
⾼阶组件装饰器写法
- 由于⾼阶组件链式调⽤的写法看起来⽐较的麻烦也不好理解。逻辑会看的⽐较绕
- ES7中就出现了装饰器的语法,专⻔拿来处理这种问题的
- 安装⽀持装饰器语法的babel编译插件
npm install --save-dev @babel/plugin-proposal-decorators - 配置⽂件
- 更改我们的启动插件,引⼊ react-app-rewired 并修改 package.json ⾥的启动配置。由于新的 react-app-rewired@2.x 版本的关系,你还需要安装 customize-cra。
yarn add react-app-rewired customize-cra - 更改package.json⽂件
/* package.json -代表没改前的代码,+代表已经更改的代码*/ "scripts": { - "start": "react-scripts start", + "start": "react-app-rewired start", - "build": "react-scripts build", + "build": "react-app-rewired build", - "test": "react-scripts test", + "test": "react-app-rewired test", } - 然后在项⽬根⽬录创建⼀个 config-overrides.js ⽤于修改默认配置
const { override, addBabelPlugins } = require('customize-cra'); module.exports = override( addBabelPlugins( [ '@babel/plugin-proposal-decorators', { legacy: true, }, ] ) ); - 执⾏安装 babel-plugin-import插件
yarn add babel-plugin-import
- 更改我们的启动插件,引⼊ react-app-rewired 并修改 package.json ⾥的启动配置。由于新的 react-app-rewired@2.x 版本的关系,你还需要安装 customize-cra。
- 重启项目
@withHOC @withLifeCycle class HOC extends Component { render() { return ( <div> <h1>{this.props.title}</h1> <p>{this.props.name}</p> </div> ); } } // 装饰器写法 export default HOC; // export default withLifeCycle(withHOC(HOC));
组件通信之上下⽂(context)
使⽤context可以避免通过中间元素传递props,context的设计⽬ 的是为了共享对于⼀个组件树⽽⾔是“全局”的数据,上下⽂context有两个⻆⾊
- Provider 数据提供
- Consumer 数据读取
import React, { Component } from 'react';
const myContext = React.createContext();
const { Provider, Consumer } = myContext;
const store = {
name: 'Steven Wong',
sex: '男',
};
const Son = (props) => {
return (
<Consumer>
{(store) => (
<div>
<h1>{store.name}</h1>
<p>{store.sex}</p>
</div>
)}
</Consumer>
);
};
const Father = (props) => {
return <Son />;
};
class Context extends Component {
render() {
return (
<Provider value={store}>
<Father />
</Provider>
);
}
}
export default Context;