React—8—受控组件和非受控组件;高阶组件

一、概念

我的理解是,是否有react提供数据,分为受控组件和非受控组件。

比如input元素,只要绑定了value属性,那么在react中,用户在输入框输入的值不会显示在输入框(react应该做了限制,原生html的input框即使value绑定了值依然可以输入),

这就导致,想改变value的值,必须监听onChange事件,然后再onChange事件里拿到用户输入的值然后再去改变message,然后value才改变。

 

 

二、使用受控组件来使用表单

复制代码
import React, { PureComponent, createRef, forwardRef } from 'react';

// 编写一个组件
class App extends PureComponent {
  constructor() {
    super();
    this.state = {
      username: '',
      password: '',

      isAgeree: false,

      hobbies: [
        { value: 'sing', text: '唱', isChecked: false },
        { value: 'dance', text: '跳', isChecked: false },
        { value: 'rap', text: 'rap', isChecked: false }
      ],

      fruit: '',
      fruits: []
    };
  }

  handleSumbit = event => {
    // 先阻止默认的事件提交。
    event.preventDefault();


    console.log(this.state)
  };

  handleChange = e => {
    // 对于类型为text或者password的输入框, 可以给input框绑定一个name属性值,然后可以通过可以e.target.name获取绑定的name属性值。
    //    通过e.target.value获取到输入框的值
    console.log('[  ] >', e.target, e.target.name);
    const { name, value } = e.target;
    this.setState({ [name]: value });
  };

  handleCheckBox = e => {
    // 对于checkbox类型的输入框, 可以通过e.target.checked获取到是否选中的ture或false;    e.target.value没有值。
    const { checked } = e.target;
    this.setState({ isAgeree: checked });
  };

  handleHobbies = (e, index) => {
    console.log(e);
    const hobbies = [...this.state.hobbies];
    hobbies[index]['isChecked'] = e.target.checked;
    this.setState({ hobbies });
  };

  handleSelect(event) {
    // seleced选中的值在event.target.selectedOptions.value
    const fruit = event.target.selectedOptions.value;
    this.setState({ fruit });
  }
  handleSelectMultiple(event) {
    //多选情况下,seleced选中的值在event.target.selectedOptions是一个集合,需要先用array.from转化为一个数组,这样就可以用数组的方法了。
    const selectedArr = Array.from(event.target.selectedOptions);
    const fruits = selectedArr.map(e => e.value);
    this.setState({ fruits });
  }

  render() {
    const { username, password, isAgeree, hobbies, fruit, fruits } = this.state;
    return (
      <div>
        <form onSubmit={e => this.handleSumbit(e)}>
          {/* 受控组件---输入框 */}
          <div>
            <label htmlFor="username">
              用户名:
              <input type="text" name="username" value={username} onChange={e => this.handleChange(e)} />
            </label>
            <label htmlFor="password">
              密码:
              <input type="password" name="password" value={password} onChange={e => this.handleChange(e)} />
            </label>
          </div>

          {/* 受控组件---单选框 */}
          <input type="checkbox" checked={isAgeree} onChange={e => this.handleCheckBox(e)} />
          同意协议

          {/* 受控组件---多选框 */}
          <div>
            {hobbies.map((item, index) => {
              return (
                <div key={item.text}>
                  <input type="checkbox" id={item.value} checked={item.isChecked} onChange={e => this.handleHobbies(e, index)} />
                  {item.text}
                </div>
              );
            })}
          </div>

          {/* 受控组件---下拉框()单选 */}
          <select name="" id="" value={fruit} onChange={e => this.handleSelect(e)}>
            <option value="orange">橘子</option>
            <option value="bnana">香蕉</option>
            <option value="putao">葡萄</option>
          </select>
          {/* 受控组件---下拉框()多选  按住ctrl键可以实现多选 */}
          <select name="" id="" value={fruits} onChange={e => this.handleSelectMultiple(e)} multiple>
            <option value="orange">橘子</option>
            <option value="bnana">香蕉</option>
            <option value="putao">葡萄</option>
          </select>
          
          <button type="submit">登录</button>
        </form>
      </div>
    );
  }
}

export default App;
复制代码

 

 

 

 

三、高阶组件hoc

 

3.1什么是高阶组件

什么是高阶组件呢?
 相信很多同学都知道(听说过?),也用过 高阶函数, 它们非常相似,所以我们可以先来回顾一下什么是 高阶函数。
 高阶函数的维基百科定义:至少满足以下条件之一:
  •  接受一个或多个函数作为输入;
  •  输出一个函数;
JavaScript中比较常见的filter、map、reduce都是高阶函数。
 
 那么说明是高阶组件呢?
 高阶组件的英文是 Higher-Order Components,简称为 HOC;
官方的定义:高阶组件是参数为组件,返回值为新组件的函数;
 我们可以进行如下的解析:
  •  首先, 高阶组件 本身不是一个组件,而是一个函数;
  • 其次,这个函数的参数是一个组件,返回值也是一个组件;

 

我们前面用的memo()和forwardRef()都是高阶组件。

 

3.2高阶组件目的是

1.对组件做拦截做处理

2.处理代码是可复用的。不用对每一个要拦截的代码,都写一遍处理代码,那是在他麻烦了。

 

3.3举例

这里,我们可以计算每个页面的挂载时长。

 

得到一个组件,可以通过props给他传递一些信息,然后最终返回一个组件(类组件和函数组件都可以),

复制代码
import { PureComponent } from 'react';

function logMountTime(OriginComponent) {
  return class extends PureComponent {
    constructor() {
      super();
      this.state = {
        foo: '这里可以添加一些处理操作'
      };
    }

    UNSAFE_componentWillMount() {
      this.beginTime = new Date().getTime();
    }

    componentDidMount() {
      this.endTime = new Date().getTime();
      console.log(`页面${OriginComponent.name}渲染时间是${this.endTime - this.beginTime}ms`);
    }

    render() {
      return <OriginComponent {...this.state}></OriginComponent>;
    }
  };
}

export default logMountTime;
复制代码

 

Head组件用高阶组件包裹之后,再export default logMountTime(Head)返回出去。

复制代码
import React, { PureComponent } from 'react'
import {  } from './hoc'
import logMountTime from './hoc'
export class Head extends PureComponent {
  render() {
    return (
      <div>
        Head
        {this.props.foo}
        <ul>
            <li>数据列表</li>
            <li>数据列表</li>
            <li>数据列表</li>
            <li>数据列表</li>
            <li>数据列表</li>
            <li>数据列表</li>
            <li>数据列表</li>
            <li>数据列表</li>
            <li>数据列表</li>
            <li>数据列表</li>
        </ul>
      </div>
    )
  }
}

// export default Head
export default logMountTime(Head)
复制代码

 

由于Head组件里是用的export Default导出的,所以App在引入的时候可以自己起别名,那就还叫Head,然后由于App组件正常引入即可展示。

复制代码
import React, { PureComponent, } from 'react';
import Head from './Head.jsx'
// 编写一个组件
class App extends PureComponent {
  constructor() {
    super();
    this.state = {

    };
  }



  render() {
   
    return (
      <div>
        <Head></Head>
      </div>
    );
  }
}

export default App;
复制代码

 

 

 

 

 

 

3.4发展历程

由于hoc也可以给组件复制props,如果嵌套过多,可以出现同一个叫name的props被重复赋值。

 mixin没必要学了,hoc可以理解,重点掌握后面的hooks。

 

posted @   Eric-Shen  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示