react中文网上这样定义高阶组件
高阶组件(HOC) 是React中用于复用组件逻辑的一种高级技巧。HOC自身不是React API的一部分, 它是一种基于React的组合特性而形成的设计模式。
综上所述:
1)高阶组件 接受一个组件作为参数, 并返回一个新组件的方法;
2)高阶组件 是一个函数, 不是组件
为什么使用高阶组件?
当多个组件都需要某个相同的功能, 使用高阶组件可以减少重复实现。
高阶组件的使用
高阶组件分为代理式 和继承式。
代理式组件:返回的组件是继承的React.Component类。被传入的组件(也叫被包裹的组件)将会在返回的新组件的render()方法中渲染出来。
继承式组件: 返回的组件是继承的是被传入的组件类。
import React, { Component } from "react";
export default ( args )=>( WrappedComponent )=>class NewComponent extends WrappedComponent{
constructor(props){
super(props);
}
render () {
return super.render();
}
}
}
(由于不推荐使用继承式组件, 所以不在讲述)
代理式组件的用法
第一种写法:(无其他参数)
此方式的高阶组件(hoc)的入参 是一个组件, 但此方式不可以有其他的参数。
import React, { Component } from "react";
function hoc ( WrappedComponent ) {
return class NewComponent extends Component{
constructor(props){
super(props);
}
render () {
return (
<WrappedComponent/>
)
}
}
}
那么在当作参数传入到高阶组件的入参组件,是如何使用高阶组件的呢?
这里会介绍两种使用高阶组件的方式, 二者只能选其一。
import React, { Component } from "react";
import hoc from "./hoc"; //引入高阶组件。找到正确的文件路径
class WrappedComponent extends Component{
constructor(props){
super(props);
}
render () {
return (
<div>我不是高阶组件, 我是高阶组件的传入组件。很普通的哦!</div>
)
}
}
export default hoc(WrappedComponent); //这是第一种,此种方法类似函数的调用
import React, { Component } from "react";
import hoc from "./hoc"; //引入高阶组件。找到正确的文件路径
@hoc //这是第二种,react中叫做装饰器,java中叫做注解。在使用这种时, 还要使用正确的babel插件,后续介绍
class WrappedComponent extends Component{
constructor(props){
super(props);
}
render () {
return (
<div>我不是高阶组件, 我是高阶组件的传入组件。很普通的哦!</div>
)
}
}
export default WrappedComponent;
第二种写法:(可以有其他参数)
此方式的高阶组件(hoc)的入参 是一个组件, 但此方式还可以有其他参数传入高阶组件中。
import React, { Component } from "react";
export default ( args )=>( WrappedComponent )=>class NewComponent extends Component{
constructor(props){
super(props);
}
render () {
return (
<WrappedComponent />
)
}
}
}
那么在当作参数传入到高阶组件的入参组件,是如何使用高阶组件的呢?
这里会介绍两种使用高阶组件的方式, 二者只能选其一。
import React, { Component } from "react";
import hoc from "./hoc"; //引入高阶组件。找到正确的文件路径
class WrappedComponent extends Component{
constructor(props){
super(props);
}
render () {
return (
<div>我不是高阶组件, 我是高阶组件的传入组件。很普通的哦!</div>
)
}
}
export default hoc()(WrappedComponent); //这是第一种,此种方法类似函数的调用 、
//注意这里的hoc调用方法,与第一种写法(无其它参数)调用方法不一样。
//无其它参数 hoc(WrappedComponent)
//有其他参数 hoc()(WrappedComponent)
import React, { Component } from "react";
import hoc from "./hoc"; //引入高阶组件。找到正确的文件路径
//注意这里的hoc调用方法,与第一种写法(无其它参数)调用方法不一样。
//无其它参数 @hoc
//有其他参数 @hoc()
@hoc() //这是第二种,react中叫做装饰器,java中叫做注解。在使用这种时, 还要使用正确的babel插件,后续介绍
class WrappedComponent extends Component{
constructor(props){
super(props);
}
render () {
return (
<div>我不是高阶组件, 我是高阶组件的传入组件。很普通的哦!</div>
)
}
}
export default WrappedComponent;
装饰器(主要讲述安装到项目中, 举例以create-react-app创建)
略定义: 装饰器是一个函数, 用@标识。可以使用在类上或者函数上。
开始讲述安装方案:
使用create-react-app创建的项目本身是不支持装饰器模式的。所以需要自己去依赖装饰器插件。
1.先安装create-react-app脚手架
npm install -g create-react-app
此时安装脚手架成功。
2.使用脚手架创建新的项目
create-react-app yourProjectName
如果此时报了
就使用
npx create-react-app yourProjectName
此时项目创建成功。
3.创建完成后,进入项目
找到根目录下的package.json文件
在终端执行下列语句
npm run eject
会输出are you want to eject ?y/n 选择y就可以了
然后会下载各种依赖,并会更新package.json里的内容。
截至到此如果运行npm run eject时,报错。则试着先输入以下命令
git add.
git commit -m "init"
后在执行一次
npm run eject
4.在package.json中添加如下语句:
"babel": {
"plugins": [
[
"@babel/plugin-proposal-decorators",
{ "legacy": true }
]
],
"presets": [ "react-app" ]
},
并下载@babel/plugin-proposal-decorators;如果失败,大多数原因是版本的原因。可自行在网络中查询对应的版本号。
到此为止, 装饰器就可以正常使用了。
5.如果不想在package.json中使用babel去处理装饰器,也可以选择在根目录创建.babelrc文件。在.babelrc文件中语句的模式与上边在package.json中类似。这里不再讲述,可以百度哟。
6.注意,package.json的babel与.babelrc文件二者选其一。
代理式模式高阶组件的功能
1.操纵props
高阶组件通过在自身处理props,再将处理好的props,传给传入组件,从而操纵传入组件的props。
import React, { Component } from "react";
export default ( args )=>( WrappedComponent )=>class NewComponent extends Component{
constructor(props){
super(props);
}
render () {
const {name, otherProps} = this.props;//将不想传入给WrappedComponent组件的props过滤出来。
return (
<div>
{/** 在WrappedComponent组件中, 就可以获取并使用高阶组件中的props了*/}
<WrappedComponent {...otherProps}/>
</div>
)
}
}
}
2.访问ref (ref不会被传递, 但可以访问)
import React, { Component } from "react";
export default ( args )=>( WrappedComponent )=>class NewComponent extends Component{
constructor(props){
super(props);
}
refs = (instance) => {
console.log(instance)//这里访问的是传入组件WrappedComponent的实例。这样就可以在高阶组件中,使用WrappedComponent的实例了。
}
render () {
const {name, otherProps} = this.props;//将不想传入给WrappedComponent组件的props过滤出来。
return (
<div>
<WrappedComponent ref = {this.refs}/>
</div>
)
}
}
}
代码是在这里纯手写, 可能会到编辑器上有些许的书写错误, 但,基本上完全可以拿去用。
-----希望有理解的不对的地方, 还要多多指出。