本文是学习慕课网 React高阶组件课程 的笔记~css
高阶组件就是接收一个组件做为参数,而后返回一个新的组件。高阶组件实际上是一个函数,并不仅是一个组件。react
加入有某需求:git
咱们对上图进行组件拆分,能够分为外部modal提示框组件和内部信息两个组件。github
外部modal组件是不变的,可是内部的内容,咱们可能在不一样的地方会显示不一样的效果。以下图。bash
因此咱们有必要去封装一个外部的modal提示框组件,去包裹不一样的内部组件。app
// 建立一个空项目
create-react-app xxx
复制代码
咱们新建几个文件。函数
// A/index.js
import React from 'react';
import './index.css';
// 定义一个函数
// 传入一个组件做为参数
function A(WrappedComponent) {
// 返回一个组件
return class A extends React.Component {
constructor (props) {
super(props);
this.state = {};
}
render () {
return (
<div className="a-container"> <div className="header"> <div className="title">提示</div> <div className="close">X</div> </div> <div> <!-- 在这里使用一下 --> <WrappedComponent /> </div> </div>
)
}
}
}
// 抛出函数
export default A
复制代码
A组件就是咱们的外部Modal提示框组件。用来包裹咱们的内部组件。学习
咱们来实现B组件。ui
// B/index.js
import React from 'react';
import A from '../A/index.js';
import './index.css';
class B extends React.Component {
render() {
return (
<div className="wrap"> <img src="https://raw.githubusercontent.com/freya0608/High-order-component/master/src/imgs/B.png" alt="" /> </div> ); } } <!--调用A()方法去包裹咱们的B组件。--> export default A(B); 复制代码
最终实现效果为:this
到此一个入门的高阶组件实例就ok了。
总结:使用高阶组件的方式:
第一种就是咱们上面的方法,第二种是利用装饰器来实现,具体的配置你们网上能够查到。
如今咱们又有了需求,就是B组件的内容,可能决定A组件的标题,因此这时候就须要咱们去经过B组件去传值给A了。
// A/index.js
import React from 'react';
import './index.css';
// 这里咱们返回一个匿名函数,接收传递得值
export default (title = '我是标题') => {
// 而后返回一个函数,这个函数接收子组件
return (WrappedComponent) => {
// 返回咱们的外部组件
return class A extends React.Component {
constructor (props) {
super(props);
this.state = {};
}
render () {
return (
<div className="a-container"> <div className="header"> <!--这里使用咱们传入的值--> <div className="title">{title}</div> <div className="close">X</div> </div> <div> <WrappedComponent /> </div> </div>
)
}
}
}
}
复制代码
// B/index.js
import React from 'react';
import A from '../A/index.js';
import './index.css';
class B extends React.Component {
render() {
return (
<div className="wrap"> <img src="https://raw.githubusercontent.com/freya0608/High-order-component/master/src/imgs/B.png" alt="" /> </div> ); } } <!-- 最主要是这里 --> export default A('提示i')(B); 复制代码
这样咱们就实现了B给A组件传值,来让A组件能动态的改变某些地方了。
认识代理方式的高阶组件咱们要从 prop、访问ref、抽取状态、包裹组件四个部分来认识。
// A/index
import React from 'react';
import './index.css';
export default (title = '我是标题') => {
return (WrappedComponent) => {
return class A extends React.Component {
constructor (props) {
super(props);
this.state = {};
}
render () {
// [1] 首先咱们能够获取到给最外层组件传递的props
const prop = this.props;
console.log(prop);
return (
<div className="a-container"> <div className="header"> <div className="title">{title}</div> <div className="close">X</div> </div> <div> <!--[2] 能够传递下去,传到B组件中--> <!--[3] 另外sex是新增的--> <WrappedComponent sex={'男'} {...this.props} /> </div> </div> ) } } } } 复制代码
// B/index.js
import React from 'react';
import A from '../A/index.js';
import './index.css';
class B extends React.Component {
render() {
return (
<div className="wrap"> <!--[1]在B组件中就能够拿到经过A组件传来的props--> 个人姓名: {this.props.name} 个人性别: {this.props.sex} <img src="https://raw.githubusercontent.com/freya0608/High-order-component/master/src/imgs/B.png" alt="" /> </div> ); } } export default A('提示i')(B); 复制代码
在APP中咱们能够设置props,传递到A组件,再由A组件筛选或者增长props,以后传给B,这样在B就能接收到最外层以及A传递来的props。一样因为A是中间层,A有权限控制B能获得哪些props,也能额外增长一些属性过去。
<B name={'zjj'}></B>
复制代码
// A/index
import React from 'react';
import './index.css';
export default (title = '我是标题') => {
return (WrappedComponent) => {
return class A extends React.Component {
constructor (props) {
super(props);
this.state = {};
}
// [1] 定义一个点击事件
handleClick = () => {
this.wref.getName();
}
render () {
const prop = this.props;
console.log(prop);
return (
<div className="a-container"> <div className="header"> <div className="title">{title}</div> <div className="close">X</div> </div> <div> <!-- 【2】绑定ref --> <WrappedComponent ref={ (v) => this.wref = v } sex={'男'} {...this.props} /> </div> <div> <!--【3】点击事件触发处--> <button onClick={this.handleClick}>获取name</button> </div> </div> ) } } } } 复制代码
咱们在B中定义一个getName方法。那么经过点击A中的按钮,就能够调用到
B/index
getName = () => {
console.log('获取到了name')
}
复制代码
// A.js
import React from 'react';
import './index.css';
export default (title = '我是标题') => {
return (WrappedComponent) => {
return class A extends React.Component {
constructor (props) {
super(props);
this.state = {
value: ''
};
}
// 点击
handleClick = () => {
this.wref.getName();
}
// [1] 根据输入设置 val
handleOnInputChange = (e) => {
this.setState({
value: e.target.value
})
}
render () {
const prop = this.props;
console.log(prop);
// [2] 设置新的props
var newProps = {
value: this.state.value, // 传入值
onInput: this.handleOnInputChange // 监听表单的输入
}
return (
<div className="a-container"> <div className="header"> <div className="title">{title}</div> <div className="close">X</div> </div> <div> <WrappedComponent ref={ (v) => this.wref = v } sex={'男'} {...this.props} {...newProps} /> // 【3】传入子组件 </div> <div> <button onClick={this.handleClick}>获取name</button> </div> </div> ) } } } } 复制代码
// B/index.js
// 使用传入的值,这样即可以将子组件内部的实现抽取出来,放到公共的组件中去,统一管理
<input type="text" value={this.props.value} onInput={this.props.onInput} />
复制代码
其实咱们上面就是实现了包裹内部组件的效果。