react高阶组件的使用教程和应用场景附源码

来源:程序思维浏览:3635次

今天咱们来说说react的高阶组件,当然咱们先要知道什么是高阶组件,它的应用场景是什么?为什么要有高阶组件的存在。

react高阶组件的使用教程和应用场景附源码

什么是高阶组件?

我们学js的时候接触过高阶函数, 高阶组件其实是差不多的用法,只不过传入的参数变成了react组件,并返回一个新的组件。

如果不知道什么是高阶函数那么看一下下面的例子:

function demo(){
  return function(){
     console.log('abc');
  }
}

demo()();

可以看到在demo函数里面又返回了一个函数这个就是高阶函数。

那么react的高阶组件如何使用呢?

高阶组件分两种形式:

1、属性代理(Props Proxy)

属性代理是最常见的高阶组件的使用方式,上述描述的高阶组件就是这种方式。它通过做一些操作,将被包裹组件的props和新生成的props一起传递给此组件,这称之为属性代理。

属性代理有如下4点常见作用:

1. 操作props
2. 通过refs访问组件实例
3. 提取state
4. 用其他元素包裹WrappedComponent,实现布局等目的


proxy.js代码如下:

import React from 'react';
import withHeader from '../../common/hoc/withHeader';
class HocComponent extends React.Component{
    constructor(){
        super();
        this.state={
            name:"张三"
        }
    };
    render(){
        return (
            <div>
                <div id="proxy">
                    我是一个属性代理的方式高阶组件<br />
                    {/*withHeader传过来的值:{this.props.name}*/}
                </div>

            </div>
        )
    }
}
export default withHeader(HocComponent,'属性代理高阶组件');

withHeader.js代码如下:

import React from 'react';
import ReactDom from "react-dom";
export default function withHeader(WrappedComponent,title) {
    return class HOC extends React.Component {
        constructor(props){
            super(props);
            this.state={
                name2:"属性代理方式"
            }
        }
        componentDidMount(){
            //获取proxy.js里面的id="proxy"的元素
            let WC=new WrappedComponent();
            let superRender=WC.render();
            let oList=ReactDom.findDOMNode(document.getElementById(superRender.props.children.props.id));
            console.log(oList.innerHTML);

        }
        render() {
            return (
                <React.Fragment>
                    <div>标题{title}</div>
                    <WrappedComponent {...this.props} name={this.state.name2}/>
                </React.Fragment>
            )
        }
    }
}

 return class HOC extends React.Component可以看到属性代理继承的是React.Component。
 

2、继承反转(Inheritance Inversion)

这种方式返回的React组件继承了被传入的组件,所以它能够访问到的区域、权限更多,相比属性代理方式,它更像打入组织内部,对其进行修改。

extend.js代码如下:

import React from 'react';
import withHeader from '../../common/hoc/extendHeader';
class HocComponent extends React.Component{
    constructor(){
        super();
        this.state={
            nickname:"张三"
        }
    };
    render(){
        return (
            <div>
                <div id="list">
                    <ul>
                        <li>我是一个反向继承的方式高阶组件</li>
                    </ul>
                </div>
            </div>
        )
    }
}

export default withHeader(HocComponent,"反向继承高阶组件");


extendHeader.js代码如下:

import React from 'react';
import ReactDom from 'react-dom';
export default function withHeader(WrappedComponent,title) {
    return class HOC extends WrappedComponent {
        constructor(){
            super();
        }
        componentDidMount(){
            //console.log(this.props);
            //可以使用extend.js里面的nickname
            console.log(this.state.nickname);
            //获取extend.js里面的id="list"的元素
            let superRender=super.render();
            let oList=ReactDom.findDOMNode(document.getElementById(superRender.props.children.props.id));
            console.log(oList.innerHTML);
        }
        render() {
            return super.render();
            // return (
            //     <React.Fragment>
            //         <div>标题{title}</div>
            //         <WrappedComponent {...this.props}/>
            //     </React.Fragment>
            // )
        }
    }
}

return class HOC extends WrappedComponent可以看到反向继承的是WrappedComponent组件。

配合有状态组件和无状态组件实战使用:

hoc.js代码如下:

import React from 'react';
import withHeader from '../../common/hoc/hocsHeader';
const WitHeader=withHeader((hocTag)=>{
    return (
        <div>我是第一个高阶组件{hocTag.children}</div>/*用hocTag.children获取name="hoc1"组件里面的内容*/
    )
});
const WitHeader2=withHeader(({children})=>{
    return (
        <div>我是第二个高阶组件{children}</div>/*用{children}获取name="hoc2"组件里面的内容*/
    )
});
const WitHeader3=withHeader((props)=>{
    return (
        <div>
            <input type="text" {...props.nickname} placeholder="输入昵称" />
            <br />
            <input type="text" {...props.pwd} placeholder="输入密码" />
        </div>
    )
});
export default class HocComponent extends React.Component{
    constructor(){
        super();
        this.state={

        }
    };
    setHoc1(){
        console.log("setHoc1");
    }
    setHoc2(){
        console.log("setHoc2");
    }
    render(){
        return (
            <div>
                <WitHeader {...this.props} name="hoc1" onClick={this.setHoc1.bind(this)}>
                    <div style={{color:"#FF0000"}}>
                        <ul>
                            <li>我是高阶组件1里面的内容</li>
                        </ul>
                    </div>
                    <div style={{color:"#0000FF"}}>
                        <ul>
                            <li>我是高阶组件1里面的内容</li>
                        </ul>
                    </div>
                </WitHeader>
                <WitHeader2 name="hoc2" onClick={this.setHoc2.bind(this)}>
                    <div style={{color:"#0000FF"}}>
                        <ul>
                            <li>我是高阶组件2里面的内容</li>
                        </ul>
                    </div>
                </WitHeader2>
                <WitHeader3></WitHeader3>
            </div>
        )
    }
}

hocsHeader.js代码如下:

import React from 'react';
export default function hocsHeader(WrappedComponent) {
    return class HOC extends React.Component {
        constructor(props){
            super(props);
            this.state={
                name:"hocsHeader",
                nickname:"",
                pwd:''
            }
        }
        componentDidMount(){
            let wrap=this.refs['wrap'];
            console.log(wrap.offsetHeight);
        }
        //获取点击事件
        getClick(){
            //接收父组件hocs.js里面的onClick事件
            if (this.props.onClick){
                this.props.onClick();
            }

        }
        changeNickname(event){
            this.setState({nickname:event.target.value},()=>{
                console.log(this.state.nickname);
            });
        }
        changePwd(event){
            this.setState({pwd:event.target.value},()=>{
                console.log(this.state.pwd);
            });
        }
        render() {
            //给hocs.js里面的WitHeader3的input添加onChange事件
            const newProps={
                nickname:{
                    value:this.state.nickname,
                    onChange:this.changeNickname.bind(this)
                },
                pwd:{
                    value:this.state.pwd,
                    onChange:this.changePwd.bind(this)
                }
            }
            return (
                <React.Fragment>
                    <div ref="wrap" onClick={this.getClick.bind(this)}>
                        <WrappedComponent {...this.props} {...newProps} />
                        {/*{this.props.children}*/}{/*获取组件hocs.js组件WitHeader和WitHeader2的内容*/}
                    </div>
                </React.Fragment>
            )
        }
    }
}

源码下载

精品好课
React实战视频教程仿京东移动端电商
React是前端最火的框架之一,就业薪资很高,本课程教您如何快速学会React并应用到实战,对正在工作当中或打算学习React高薪就业的你来说,那么这门课程便是你手中的葵花宝典。
最新完整React视频教程从入门到精通纯干货纯实战
React是目前最火的前端框架,就业薪资很高,本课程教您如何快速学会React并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习React高薪就...
VUE2+VUE3视频教程从入门到精通(全网最全的Vue课程)
VUE是目前最火的前端框架之一,就业薪资很高,本课程教您如何快速学会VUE+ES6并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习VUE高薪就...
Vue2+Vue3+ES6+TS+Uni-app开发微信小程序从入门到实战视频教程
2021年最新Vue2+Vue3+ES6+TypeScript和uni-app开发微信小程序从入门到实战视频教程,本课程教你如何快速学会VUE和uni-app并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己...
jQuery视频教程从入门到精通
jquery视频教程从入门到精通,课程主要包含:jquery选择器、jquery事件、jquery文档操作、动画、Ajax、jquery插件的制作、jquery下拉无限加载插件的制作等等......
最新完整React+VUE视频教程从入门到精,企业级实战项目
React和VUE是目前最火的前端框架,就业薪资很高,本课程教您如何快速学会React和VUE并应用到实战,教你如何解决内存泄漏,常用库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习Re...
HTML5视频播放器video开发教程
适用人群1、有html基础2、有css基础3、有javascript基础课程概述手把手教你如何开发属于自己的HTML5视频播放器,利用mp4转成m3u8格式的视频,并在移动端和PC端进行播放支持m3u8直播格式,兼容...
HTML5基础入门视频教程易学必会
HTML5基础入门视频教程,教学思路清晰,简单易学必会。适合人群:创业者,只要会打字,对互联网编程感兴趣都可以学。课程概述:该课程主要讲解HTML(学习HTML5的必备基础语言)、CSS3、Javascript(学习...
收藏
扫一扫关注我们