第一章 引导
学习之前要有一定的:es6基础、js面向对象编程、react的一些基础知识
第二章 高阶组件介绍
2-1 高阶函数
1、高阶函数的两个基本特征
//1.函数可以做为参数被传递
setTimeout(function(){
console.log(1)
},1000)
//2.函数可以作为返回值输出
function student(name){
return function(){
return name
}
}
2、应用场景:
1).高阶函数在时间函数的应用
setTimeout()
setInterval()
2).高阶函数在ajax中的应用
$.get('/api/api.json',function(){
console.log('获取成功')
})
3).高阶函数在数组中的应用
some()
every()
filter()
map()
forEach()
2-2 高阶组件介绍
1、高阶组件基本概念(High Order Component,HOC)
高阶组件就是:接受一个组件作为参数并返回一个新的组件的函数
高阶组件:是一个函数,并不是组件
代码演示地址:https://gitee.com/sunnyfan/react-hight-order-component.git
git clone https://gitee.com/sunnyfan/react-hight-order-component.git
cd react-hight-order-component
npm install
npm start
代码截取
//1.组件A是公共组件,且被定义为一个高阶组件(高阶函数)
import React, {Component} from 'react';
function A(WrappedComponent) {
return class A extends Component {
render() {
return (
<div className="container">
<div className="header">
<span>提示</span>
<span>X</span>
</div>
<div className="content">
<WrappedComponent></WrappedComponent>
</div>
</div>
);
}
}
}
export default A;
//B组件
import React, {Component} from 'react';
import A from './A';
class B extends Component {
render() {
return (
<div>
B
</div>
);
}
}
export default A(B);
//C组件
import React, {Component} from 'react';
import A from './A';
class C extends Component {
render() {
return (
<div>
c
</div>
);
}
}
export default A(C);
应为A组件是公共组件,在B和C组件中都被使用到了,所以可以把A抽离成为公共组件
2、使用场景
多个组件都需要某个相同的功能,使用高阶组件减少重复实现
3、高阶组件实例
react-redux中的connect
export default connect(mapStateToProps,mapDispatchToProps)(Header);
第三章 高阶组价实现
3-1编写高阶组件
1.实现一个普通组件
2.将普通组件使用函数包裹
//第一步:实现一个普通组件
import React, {Component} from 'react';
class A extends Component {
render() {
return (
<div>
A
</div>
);
}
}
export default A;
//将普通组件使用函数包裹
import React, {Component} from 'react';
function A(WrappedComponent) {
return class A extends Component {
render() {
return (
<div className="container">
<WrappedComponent />
</div>
);
}
}
}
export default A;
3-1使用高阶组件
1.higherOrderComponent(WrappedComponent);
2.@higherOrderComponent 通过装饰器
要想使用装饰器的用法:那么我们需要对项目进行一些配置
1).开启webpack配置项
在创建的create-react-app项目中 运行 npm run eject
2).安装两个依赖包
npm install babel-preset-stage-2 -D
npm install babel-preset-react-native-stage-0 -D
或者(简写如下):
npm install babel-preset-stage-2 babel-preset-react-native-stage-0 -D
3).项目根目录创建.babelrc配置文件
//.babelrc
{
"presets":["react-native-stage-0/decorator-support"]
}
ps:如果上面出现报错
Cannot find module 'react-native-stage-0/decorator-suppor
npm install metro-react-native-babel-preset -D
将.babelrc改为
{
"presets": ["module:metro-react-native-babel-preset"],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }]
]
}
配置好后,那么怎么在项目中使用@装饰器来替代写法呢
import React, {Component} from 'react';
import A from './A';
@A //第二种使用方法:通过装饰器
class B extends Component {
render() {
return (
<div>
B
</div>
);
}
}
//export default A(B); 第一种使用方法:高阶组件的普通使用
export default B //如果上面使用了@A 那么这个地方直接这样写即可
第四章高阶组件的应用
4-1 高阶组件的代理方式
1、代理方式的高阶组件
返回的新组件类直接继承自React.Component类
新组件扮演的角色传入参数组件的一个代理,在新组件的render函数中,将被包裹组件渲染出来,除了高阶组件自己要做的工作,其他功能全局转手给了被包裹的组件
- 操纵prop
- 抽离状态
- 访问ref
- 包装组件
1.1.操纵props
高阶组件是如何向子组件传递参数或者值的呢?
高阶组件是如何去除组件当中的属性或者值的呢?
import React, {Component} from 'react';
function A(WrappedComponent) {
return class A extends Component {
render() {
const {age, ...otherProps} = this.props
return (
<div className="container">
<div className="header">
<span>提示</span>
<span>X</span>
</div>
<div className="content">
<WrappedComponent
name={'张三'}
sex={'男'}
{...otherProps}
/>
</div>
</div>
);
}
}
}
export default A;
通过属性值 给子组件传值:age={'18'}
通过结构的方式去除,其他的参数或者属性:
//这样就把age的属性从所有属性值剔除出去了
const {age, ...otherProps} = this.props;
<WrappedComponent
name={'张三'}
sex={'男'}
{...otherProps}
/>
1.2.访问ref
//A组件
import React, {Component} from 'react';
function A(WrappedComponent) {
return class A extends Component {
componentDidMount() {
const value = this.refs
console.log(value.getName())
}
render() {
const {age, ...otherProps} = this.props
return (
<div className="container">
<div className="header">
<span>提示</span>
<span>X</span>
</div>
<div className="content">
<WrappedComponent
name={'张三'}
sex={'男'}
{...otherProps}
ref={(value) => this.refs = value}>
</WrappedComponent>
</div>
</div>
);
}
}
}
export default A;
//B组件
import React, {Component} from 'react';
import A from './A';
@A
class B extends Component {
getName() {
return '我是B组件'
}
render() {
const {name, age, sex} = this.props;
return (
<div>
B
</div>
);
}
}
export default B;
1.3 抽取状态
//A组件
import React, {Component} from 'react';
function A(WrappedComponent) {
return class A extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: '张三'
}
}
handleChangeValue = (e) => {
const value = e.target.value;
this.setState({
inputValue: value
})
}
render() {
const {age, ...otherProps} = this.props;
const {inputValue} = this.state;
const newProps = {
value: inputValue,
onChange: this.handleChangeValue,
placeholder: '张三'
}
return (
<div className="container">
<div className="header">
<span>提示</span>
<span>X</span>
</div>
<div className="content">
<WrappedComponent
name={'张三'}
sex={'男'}
{...otherProps}
{...newProps}
/>
</div>
</div>
)
;
}
}
}
export default A;
//B组件
import React, {Component} from 'react';
import A from './A';
@A
class B extends Component {
render() {
const {age, sex, ...newProps} = this.props;
return (
<div>
<p>
<label>请输入我的名字:</label>
<input
type="text"
value={newProps.value}
onChange={newProps.onChange}
placeholder={newProps.placeholder}
/>
</p>
<p>
我的名字:{newProps.value}
</p>
</div>
);
}
}
export default B;
4-2 继承方式的高阶组件
采用继承关联作为参数的组件和返回的组件,假如传入的组件参数是WrappedComponent,那么返回的组件就直接继承自WrappedComponent
2.1代理方式的高阶组件和继承方式的高阶组件的区别
- 操作props
- 操作生命周期函数
//组件D 继承方式的高阶组件
import React from 'react';
const modifyPropsHOC = (WrappedComponent) => class NewComponent extends WrappedComponent {
componentWillMount() {
alert('我是在继承生命周期函数')
}
render() {
const element = super.render();
const newStyle = {
color: element.type === 'div' ? 'red' : 'green'
};
const newProps = {...this.props, style: newStyle};
return React.cloneElement(element, newProps, element.props.children)
}
};
export default modifyPropsHOC
//E组件 继承D里面一些
import React, {Component} from 'react';
import D from './D';
@D
class E extends Component {
componentWillMount() {
alert('我是原始生命周期函数')
}
render() {
return (
<div>
我是div
</div>
);
}
}
export default E;
ps:我们应该“代理方式”优先于“继承方式”的
所以我们在开发过程中,尽量是用代理方式的高阶组件
4-3高阶组件显示名
通过高阶组件中有一个displayName的属性来显示的
import React from 'react';
const modifyPropsHOC = (WrappedComponent) => class NewComponent extends WrappedComponent {
static displayName = `NewComponent(${getDisplayName(WrappedComponent)})`; //这里设置组件名称
render() {
const element = super.render();
const newStyle = {
color: element.type === 'div' ? 'red' : 'green'
};
const newProps = {...this.props, style: newStyle};
return React.cloneElement(element, newProps, element.props.children)
}
};
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}
export default modifyPropsHOC
第五章 高阶组件的实际应用-底部导航切换
代码地址
git clone https://gitee.com/sunnyfan/react-hight-order-component.git
git checkout feature/shili