React 高阶组件

React高阶组件

本文是学习慕课网 React高阶组件课程 的笔记~css

1、什么是React高阶组件

高阶组件就是接收一个组件做为参数,而后返回一个新的组件。高阶组件实际上是一个函数,并不仅是一个组件。react

2、入门Demo来认识高阶组件

一、需求分析

加入有某需求:git

咱们对上图进行组件拆分,能够分为外部modal提示框组件和内部信息两个组件。github

外部modal组件是不变的,可是内部的内容,咱们可能在不一样的地方会显示不一样的效果。以下图。bash

因此咱们有必要去封装一个外部的modal提示框组件,去包裹不一样的内部组件。app

二、项目构建

// 建立一个空项目
create-react-app xxx
复制代码

咱们新建几个文件。函数

// A/index.js

import React from 'react';
import './index.css';

// 定义一个函数
// 传入一个组件做为参数
function A(WrappedComponent) {
  // 返回一个组件
  return class A extends React.Component {
    constructor (props) {
      super(props);
      this.state = {};
    }

    render () {
      return (
        <div className="a-container"> <div className="header"> <div className="title">提示</div> <div className="close">X</div> </div> <div> <!-- 在这里使用一下 --> <WrappedComponent /> </div> </div>
      )
    }
  }
}

// 抛出函数
export default A

复制代码

A组件就是咱们的外部Modal提示框组件。用来包裹咱们的内部组件。学习

咱们来实现B组件。ui

// B/index.js

import React from 'react';
import A from '../A/index.js';
import './index.css';


class B extends React.Component {
    render() {
        return (
            <div className="wrap"> <img src="https://raw.githubusercontent.com/freya0608/High-order-component/master/src/imgs/B.png" alt="" /> </div> ); } } <!--调用A()方法去包裹咱们的B组件。--> export default A(B); 复制代码

最终实现效果为:this

到此一个入门的高阶组件实例就ok了。

总结:使用高阶组件的方式:

第一种就是咱们上面的方法,第二种是利用装饰器来实现,具体的配置你们网上能够查到。

如今咱们又有了需求,就是B组件的内容,可能决定A组件的标题,因此这时候就须要咱们去经过B组件去传值给A了。

// A/index.js

import React from 'react';
import './index.css';

// 这里咱们返回一个匿名函数,接收传递得值
export default (title = '我是标题') => {

  // 而后返回一个函数,这个函数接收子组件 
  return (WrappedComponent) => {
    // 返回咱们的外部组件
    return class A extends React.Component {
      constructor (props) {
        super(props);
        this.state = {};
      }

      render () {
        return (
          <div className="a-container"> <div className="header"> <!--这里使用咱们传入的值--> <div className="title">{title}</div> <div className="close">X</div> </div> <div> <WrappedComponent /> </div> </div>
        )
      }
    }
  }
}
复制代码
// B/index.js
import React from 'react';
import A from '../A/index.js';
import './index.css';
class B extends React.Component {
    render() {
        return (
            <div className="wrap"> <img src="https://raw.githubusercontent.com/freya0608/High-order-component/master/src/imgs/B.png" alt="" /> </div> ); } } <!-- 最主要是这里 --> export default A('提示i')(B); 复制代码

这样咱们就实现了B给A组件传值,来让A组件能动态的改变某些地方了。

3、代理方式的高阶组件

认识代理方式的高阶组件咱们要从 prop、访问ref、抽取状态、包裹组件四个部分来认识。

  • props
// A/index

import React from 'react';
import './index.css';

export default (title = '我是标题') => {
  return (WrappedComponent) => {
    return class A extends React.Component {
      constructor (props) {
        super(props);
        this.state = {};
      }

      render () {
        // [1] 首先咱们能够获取到给最外层组件传递的props
        const prop = this.props;
        console.log(prop);

        
        return (
          <div className="a-container"> <div className="header"> <div className="title">{title}</div> <div className="close">X</div> </div> <div> <!--[2] 能够传递下去,传到B组件中--> <!--[3] 另外sex是新增的--> <WrappedComponent sex={'男'} {...this.props} /> </div> </div> ) } } } } 复制代码
// B/index.js

import React from 'react';
import A from '../A/index.js';
import './index.css';
class B extends React.Component {
    render() {
        return (
            <div className="wrap"> <!--[1]在B组件中就能够拿到经过A组件传来的props--> 个人姓名: {this.props.name} 个人性别: {this.props.sex} <img src="https://raw.githubusercontent.com/freya0608/High-order-component/master/src/imgs/B.png" alt="" /> </div> ); } } export default A('提示i')(B); 复制代码

在APP中咱们能够设置props,传递到A组件,再由A组件筛选或者增长props,以后传给B,这样在B就能接收到最外层以及A传递来的props。一样因为A是中间层,A有权限控制B能获得哪些props,也能额外增长一些属性过去。

<B name={'zjj'}></B>
复制代码
  • refs
// A/index

import React from 'react';
import './index.css';

export default (title = '我是标题') => {
  return (WrappedComponent) => {
    return class A extends React.Component {
      constructor (props) {
        super(props);
        this.state = {};
      }
      // [1] 定义一个点击事件
      handleClick = () => {
        this.wref.getName();
      }


      render () {
        const prop = this.props;
        console.log(prop);
        return (
          <div className="a-container"> <div className="header"> <div className="title">{title}</div> <div className="close">X</div> </div> <div> <!-- 【2】绑定ref --> <WrappedComponent ref={ (v) => this.wref = v } sex={'男'} {...this.props} /> </div> <div> <!--【3】点击事件触发处--> <button onClick={this.handleClick}>获取name</button> </div> </div> ) } } } } 复制代码

咱们在B中定义一个getName方法。那么经过点击A中的按钮,就能够调用到

B/index

getName = () => {
  console.log('获取到了name')
}
复制代码
  • 抽取状态
// A.js
import React from 'react';
import './index.css';

export default (title = '我是标题') => {
  return (WrappedComponent) => {
    return class A extends React.Component {
      constructor (props) {
        super(props);
        this.state = {
          value: ''
        };
      }

      // 点击
      handleClick = () => {
        this.wref.getName();
      }

      // [1] 根据输入设置 val
      handleOnInputChange = (e) => {
        this.setState({
          value: e.target.value
        })
      }

      render () {
        const prop = this.props;
        console.log(prop);
        
        // [2] 设置新的props
        var newProps = {
          value: this.state.value, // 传入值
          onInput: this.handleOnInputChange // 监听表单的输入
        }
        return (
          <div className="a-container"> <div className="header"> <div className="title">{title}</div> <div className="close">X</div> </div> <div> <WrappedComponent ref={ (v) => this.wref = v } sex={'男'} {...this.props} {...newProps} /> // 【3】传入子组件 </div> <div> <button onClick={this.handleClick}>获取name</button> </div> </div> ) } } } } 复制代码
// B/index.js
// 使用传入的值,这样即可以将子组件内部的实现抽取出来,放到公共的组件中去,统一管理
<input type="text" value={this.props.value} onInput={this.props.onInput} />
复制代码
  • 包装组件

其实咱们上面就是实现了包裹内部组件的效果。

相关文章
相关标签/搜索