react 高阶组件
demo代码
1、高阶函数
在学习之前首先说一下高阶函数的基本概念:
- 函数可以作为参数被传递
- 函数可以作为返回值输出
像平时js 中我们用到的以下这些都是 高阶函数
setTimeout(() => {
console.log(1)
}, 1000)
setInterval(() => {
console.log(1)z
}, 1000)
function foo (x) {
return function () {
return x
}
}
//包括 Array 对象中提供的原生方法
some()
every()
map()
forEach()
// 等方法 都是高阶函数
2、高阶组件介绍
- 高阶组件就是接受一个组件作为参数并返回一个新组件的函数
- 高阶组件是一个函数,并不是组件
3、为什么需要高阶组件
- 多个组件都需要某个相同的功能,使用高阶组件减少重复实现。就像 vue 的 mixin
4、简单实现一个高阶组件
-
components/
下的文件夹按照顺序学习 -
components/demo1
是简单实现一个 高阶函数,并且还可以使用修饰符@
但是需要配置 @babel/plugin-proposal-decorators 以后才可以使用 否则报错
配置方法:create-react-app装饰器 运行环境配置步骤
5、代理方式的高阶组件
compoonents/demo2 - demo4
实现代理方式的高阶组件- 代理方式高阶组件概述:
返回的新组件类直接继承自
React.Component
类,新组件扮演的角色传入参数数组的一个代理,在新组件的render
函数中,将被包裹组件渲染出来,除了高阶组件自己要做的工作,其余功能全部转手给了被包裹的组件。这段话比较抽象,可以结合demo2 - demo4
下的代码来理解。
- 实现的功能:
- 操作 prop
对应 /demo2
- 访问 ref
对应 /demo3
- 抽取状态
对应 /demo4
- 包装组件
包装组件顾名思义就是用标签 把传入的组件包裹起来,其实上边的每个demo中传入的组件 WrappedComponent 都是被包装过的
- 生命周期函数
对应 /demo4 不管是作为参数传入高阶组件的组件,还是高阶组件,只要组件中有生命周期函数,他们都不会相互干扰,都会被执行,执行顺序是:先执行作为参数传入高阶组件的组件内的生命周期先执行,高阶组件中的生命周期后执行,如下图
- 操作 prop
6、继承方式的高阶组件
- 继承方式高阶组件概述:
采用继承关联作为参数的组件和返回的组件,加入传入的组件参数是
WrappedComponent
,那么返回的组件就直接继承自WrappedComponent
,结合代码来理解,继承方式的高阶函数应用场景很少,工作中主要还是使用 搭理方式高阶函数;
- 实现的功能:
- 操作prop
对应 /demo5
- 操作生命周期函数
对应/demo6 如果作为参数传入高阶组件的组件中有生命周期,并且高阶函数中也有相同的生命周期,那么被传入的组件中的生命周期会被 高阶组件中的生命周期函数覆盖, 如下图,分别在 B(作为参数传入高阶组件 A 的组件) 组件中使用了 componentDidMount, 和高阶组件中使用了componentDidMount,这时候高阶组件中的 生命周期函数执行了两次,但是 B 组件中的生命周期没有执行, 高阶组件中的生命周期函数执行了两次,是因为有两个组件使用了这个高阶组件
- 操作prop
7、高阶组件显示名字
- 正常情况下 使用继承方式的高阶组件,使用 react-devtools 调试代码的时候,会发现,作为传入参数的 B C 组件不能显示出组件名字,只会显示出高阶组件的名字,这样调试起来可能就不是很方便,如下图
- 同样react 也提供了相应的静态属性
static displayName
来处理 :具体代码参照/demo7
中的代码,修改过后展示方式如下:
8、使用高阶组件实现手机端底部 TabBar 导航栏
- 具体实现代码参照
components/tabbar
,通常情况下,手机端的他底部导航栏,我们都是封装成一个组件的,具体哪个路由页面使用的话就再哪个文件里引用即可,这里吧 TabBar 组件改成了高阶组件,哪个路由页面使用直接把哪个文件的组件作为参数传入到 TabBar 组件中渲染;效果图如下: