高阶组件&&高阶函数(一)
antd里面的form表单方面,遇到一个高阶函数,以及高阶组件,于是看了一下这方面内容,前辈们的文章写得也非常详细,这里就稍微kobe一下
高阶函数与高阶组件
高阶函数:
高阶函数,是一种特别的函数,接受的参数为函数,返回值也是函数
成立条件,二者兼一即可
1).一类特别的函数
a).接受函数类型的参数
b).函数返回值是函数
常见的高阶函数:
2).常见 a).定时器:setTimeout()/setInterval() b).Promise:Promise(()=>{}) then(value=>{},reason=>{}) c).数组遍历相关的方法: forEach()/ filter()/ map()/ find()/ findindex() d).fn.bind() 本身是个函数,bind方法返回一个新的函数方法 e).Form.create()() create函数能够包装组件,生成另外一个组件的新功能函数 f).getFieldDecorator()()
1)函数作为参数的高阶函数 setTimeout(()=>{ console.log("aaaa") },1000)
//2 函数作为返回值输出的高阶函数 function foo(x){ return function(){ return x } } //平时遇到的应用场景 //ajax中 $.get("/api",function(){ console.log("获取成功") }) //数组中 some(), every(),filter(), map()和forEach()
高阶组件
1 高阶组件就是接受一个组件作为参数并返回一个新组件的函数
2 高阶组件是一个函数,并不一个组件
简单说:高阶组件(函数)就好比一个加工厂,同样的配件、外壳、电池..工厂组装完成就是苹果手机,华为手机组装完成就是华为手机,基本材料都是相同,不同工厂(高阶组件)有不同的实现及产出。当然这个工厂(高阶组件)也可能是针对某个基本材料的处理,总之产出的结果拥有了输入组件不具备的功能,输入的组件可以是一个组件的实例,也可以是一个组件类,还可以是一个无状态组件的函数
解决什么问题?
随着项目越来越复杂,开发过程中,多个组件需要某个功能,而且这个功能和页面并没有关系,所以也不能简单的抽取成一个新的组件,但是如果让同样的逻辑在各个组件里各自实现,无疑会导致重复的代码。比如页面有三种弹窗一个有title,一个没有,一个又有右上角关闭按钮,除此之外别无它样,你总不能整好几个弹窗组件吧,这里除了tilte,关闭按钮其他的就可以做为上面说的基本材料。
高阶组件总共分为两大类
- 代理方式
- 操纵prop
- 访问ref(不推荐)
- 抽取状态
- 包装组件
- 继承方式
- 操纵生命周期
- 操纵prop
代理方式之 操纵prop
删除prop
import React from 'react' function HocRemoveProp(WrappedComponent) { return class WrappingComPonent extends React.Component { render() { const { user, ...otherProps } = this.props; return <WrappedComponent {...otherProps} /> } } } export default HocRemoveProp;
增加prop
import React from 'react' const HocAddProp = (WrappedComponent,uid) => class extends React.Component { render() { const newProps = { uid, }; return <WrappedComponent {...this.props} {...newProps} /> } } export default HocAddProp;
上面HocRemoveProp高阶组件中,所做的事情和输入组件WrappedComponent功能一样,只是忽略了名为user的prop。也就是说,如果WrappedComponent能处理名为user的prop,这个高阶组件返回的组件则完全无视这个prop。
const { user, ...otherProps } = this.props;
这是一个利用es6语法技巧,经过上面的语句,otherProps里面就有this.props中所有的字段除了user.
假如我们现在不希望某个组件接收user的prop,那么我们就不要直接使用这个组件,而是把这个组件作为参数传递给HocRemoveProp,然后我们把这个函数的返回结果当作组件来使用
两个高阶组件的使用方法:
const newComponent = HocRemoveProp(SampleComponent);
const newComponent = HocAddProp(SampleComponent,'1111111');
也可以利用decorator语法糖这样使用:
import React, { Component } from 'React'; @HocRemoveProp class SampleComponent extends Component { render() {} } export default SampleComponent;
//例子: A组件里面包含B组件 import React , { Component }from 'react' function A(WrappedComponent){ return class A extends Component{ //这里必须retrun出去 render() { return( <div> 这是A组件 <WrappedComponent></WrappedComponent> </div> ) } } } export default A
高阶组件应用:
//传参数 import React, { Component } from 'react'; import './App.css'; import B from './components/B' class App extends Component { render() { return ( <div className="App"> 这是我的APP <B age="18" name="Tom"/> </div> ); } } export default App; //A组件 import React , { Component }from 'react' export default (title)=> WrappedComponent => { return class A extends Component{ render() { return( <div> 这是A组件{title} <WrappedComponent sex="男" {...this.props}></WrappedComponent> </div> ) } } } //B组件 import React , { Component }from 'react' import A from './A.js' class B extends Component{ render() { return( <div> 性别:{this.props.sex} 年龄:{this.props.age} 姓名:{this.props.name} </div> ) } } export default A('提示')(B) //有两种方式引用高阶函数,第一种入上 //第二种 import React , { Component }from 'react' import a from './A.js' @a('提示') class B extends Component{ render() { return( <div> 性别:{this.props.sex} 年龄:{this.props.age} 姓名:{this.props.name} </div> ) } } export default B
使用高阶组件
1.higherOrderComponent(WrappedComponent);
2.@higherOrderComponent
高阶组件应用
1.代理方式的高阶组件 返回的新组件类直接继承自React.Component类,新组件扮演的角色传入参数组件的一个代理,
在新组件的render函数中,将被包裹组件渲染出来,除了高阶组件自己要做的工作,其余功能全都转手给了被包裹的组件 2.继承方式的高阶组件 采用继承关联作为参数的组件和返回的组件,假如传入的组件参数是WrappedComponent,那么返回的组件就直接继承自WrappedComponent
//代理方式的高阶组件 export default ()=> WrappedComponent => class A extends Component { render(){ const { ...otherProps } = this.props; return <WrappedComponent {...otherProps} /> } } //继承方式的高阶组件 export default () => WrappedComponent => class A extends WrappedComponent { render(){ const { use,...otherProps } = this.props; this.props = otherProps; return super.render() } }
继承方式高阶组件的实现
//D.js import React from 'react' const modifyPropsHOC= (WrappedComponent) => class NewComponent extends 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) } } export default modifyPropsHOC // E.js import React, {Component} from 'react' import D from './D' class E extends Component { render(){ return ( <div> 我的div </div> ); } } export default D(E) // F.js import React, {Component} from 'react' import d from './D' class F extends Component { render(){ return ( <p> 我的p </p> ); } } export default d(F) import React, { Component } from 'react'; import './App.css'; import E from './components/E' import F from './components/F' class App extends Component { render() { return ( <div className="App"> 这是我的APP <E></E> <F></F> </div> ); } } export default App;
修改生命周期
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