react之高阶组件


高阶函数定义

如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数。

1.若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数。

2.若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。

简单理解就是:

高阶函数是一个特别的函数,接受函数类型的参数,返回值是也是函数

常见的高阶函数有

​ a. 定时器: setTimeout()/setInterval()

​ b. Promise: Promise(() => {}) then(value => {}, reason => {})

​ c. 数组遍历相关的方法: forEach()/filter()/map()/reduce()/find()/findIndex()

​ d. 函数对象的bind()

​ e. Form.create()() / getFieldDecorator()()

我现在编写一个高阶函数的实例,需求是这样,在输入框输入相应值,点击确定按钮弹出输入的值

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <title>高阶函数_函数柯里化</title>
</head>

<body>
    <!-- 准备好一个“容器” -->
    <div id="test"></div>

    <!-- 引入react核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入react-dom,用于支持react操作DOM -->
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>
    <script type="text/babel">

        //创建组件
        class Login extends React.Component {
            //初始化状态
            state = {
                username: '', //用户名
                password: '', //密码
            };

            //保存表单数据到状态中
            saveFormData = (dataType) => { //saveFormData这个就是一个高阶函数
                return (event) => {
                    this.setState({ [dataType]: event.target.value });
                };
            };

            //表单提交的回调
            handleSubmit = (event) => {
                event.preventDefault(); //阻止表单提交
                const { username, password } = this.state;
                alert(`你输入的用户名是:${username},你输入的密码是:${password}`);
            };
            render() {
                return (
                    <form onSubmit={this.handleSubmit}>
                        用户名:
                        <input
                            onChange={this.saveFormData('username')}
                            type="text"
                            name="username"
                        />
              密码:
                        <input
                            onChange={this.saveFormData('password')}
                            type="password"
                            name="password"
                        />
                        <button>登录</button>
                    </form>
                );
            }
        }
        //渲染组件
        ReactDOM.render(<Login />, document.getElementById('test'));
    </script>
</body>

</html>

以上saveFormData这个就是一个高阶函数,因为它满足高阶函数的定义条件。

高阶组件的定义

高阶组件(HOC)就是接受一个组件作为参数并返回一个新组件的函数。这里需要注意高阶组件是一个函数,并不是组件,这一点一定要注意。
同时这里强调一点高阶组件本身并不是 React API。它只是一种模式,这种模式是由 React 自身的组合性质必然产生的。

简单理解就是:​ 本质就是一个函数定义,且该函数接受一个组件作为参数,并返回一个新的组件。

1、最普通的组件

welcome函数转为react组件。

import React, {Component} from 'react'

class Welcome extends Component {
    constructor(props) {
        super(props);
        this.state = {
            username: ''
        }
    }

    componentWillMount() {
        let username = localStorage.getItem('username');
        this.setState({
            username: username
        })
    }

    render() {
        return (
            <div>welcome {this.state.username}</div>
        )
    }
}

export default Welcome;

goodbey函数转为react组件。

import React, {Component} from 'react'

class Goodbye extends Component {
    constructor(props) {
        super(props);
        this.state = {
            username: ''
        }
    }

    componentWillMount() {
        let username = localStorage.getItem('username');
        this.setState({
            username: username
        })
    }

    render() {
        return (
            <div>goodbye {this.state.username}</div>
        )
    }
}

export default Goodbye;

我们发现两个组件中有一句代码是一样的,这叫冗余。
我们来写一个高阶组件(高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件)。

import React, {Component} from 'react'

export default (WrappedComponent) => {
    class NewComponent extends Component {
        constructor() {
            super();
            this.state = {
                username: ''
            }
        }

        componentWillMount() {
            let username = localStorage.getItem('username');
            this.setState({
                username: username
            })
        }

        render() {
            return <WrappedComponent username={this.state.username}/>
        }
    }

    return NewComponent
}

这样我们就能简化Welcome组件和Goodbye组件。

import React, {Component} from 'react';
import wrapWithUsername from 'wrapWithUsername';

class Welcome extends Component {

    render() {
        return (
            <div>welcome {this.props.username}</div>
        )
    }
}

Welcome = wrapWithUsername(Welcome);

export default Welcome;
import React, {Component} from 'react';
import wrapWithUsername from 'wrapWithUsername';

class Goodbye extends Component {

    render() {
        return (
            <div>goodbye {this.props.username}</div>
        )
    }
}

Goodbye = wrapWithUsername(Goodbye);

export default Goodbye;

高阶组件就是把username通过props传递给目标组件了。目标组件只管从props里面拿来用就好了。

例子2

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>高阶组件例子</title>
  </head>

  <body>
    <!-- 准备好一个“容器” -->
    <div id="test"></div>

    <!-- 引入react核心库 -->
    <script type="text/javascript" src="../js/react.development.js"></script>
    <!-- 引入react-dom,用于支持react操作DOM -->
    <script
      type="text/javascript"
      src="../js/react-dom.development.js"
    ></script>
    <!-- 引入babel,用于将jsx转为js -->
    <script type="text/javascript" src="../js/babel.min.js"></script>
    <script type="text/babel">
      function withHeader(WrappedComponent) {
        return class HOC extends React.Component {
          render() {
            return (
              <div>
                <legend>默认标题</legend>
                <WrappedComponent {...this.props} />
              </div>
            );
          }
        };
      }
      class Demo extends React.Component {
        render() {
          return <div>我是一个普通组件</div>;
        }
      }
      const WithHeaderDemo = withHeader(Demo);

      //渲染组件
      ReactDOM.render(<WithHeaderDemo />, document.getElementById('test'));
    </script>
  </body>
</html>

文章作者: BiLiang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 BiLiang !
评论
  目录